Upload 1527 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +30 -0
- LICENSE +21 -0
- README.md +40 -10
- demonstration/detection.png +0 -0
- demonstration/kinds.png +0 -0
- demonstration/main.png +3 -0
- demonstration/record.png +0 -0
- demonstration/trend.png +0 -0
- detectweb/__init__.py +73 -0
- detectweb/__pycache__/__init__.cpython-37.pyc +0 -0
- detectweb/__pycache__/config.cpython-37.pyc +0 -0
- detectweb/__pycache__/email_.cpython-37.pyc +0 -0
- detectweb/__pycache__/forms.cpython-37.pyc +0 -0
- detectweb/__pycache__/label_image.cpython-37.pyc +0 -0
- detectweb/__pycache__/model.cpython-37.pyc +0 -0
- detectweb/__pycache__/route.cpython-37.pyc +0 -0
- detectweb/__pycache__/utils.cpython-37.pyc +0 -0
- detectweb/config.py +28 -0
- detectweb/detectweb.db +0 -0
- detectweb/email_.py +27 -0
- detectweb/forms.py +64 -0
- detectweb/label_image.py +139 -0
- detectweb/model.py +34 -0
- detectweb/models/__init__.py +0 -0
- detectweb/models/__pycache__/__init__.cpython-37.pyc +0 -0
- detectweb/models/__pycache__/predict.cpython-37.pyc +0 -0
- detectweb/models/__pycache__/tweet.cpython-37.pyc +0 -0
- detectweb/models/__pycache__/user.cpython-37.pyc +0 -0
- detectweb/models/predict.py +20 -0
- detectweb/models/tweet.py +17 -0
- detectweb/models/user.py +135 -0
- detectweb/route.py +546 -0
- detectweb/templates/404.html +7 -0
- detectweb/templates/_tweets.html +18 -0
- detectweb/templates/articles/article1.html +97 -0
- detectweb/templates/articles/article2.html +106 -0
- detectweb/templates/base.html +67 -0
- detectweb/templates/dashboard.html +150 -0
- detectweb/templates/edit_profile.html +21 -0
- detectweb/templates/email/passwd_reset.html +11 -0
- detectweb/templates/email/passwd_reset.txt +10 -0
- detectweb/templates/email/user_activate.html +5 -0
- detectweb/templates/email/user_activate.txt +5 -0
- detectweb/templates/explore.html +14 -0
- detectweb/templates/feedback.html +57 -0
- detectweb/templates/feedback_history.html +67 -0
- detectweb/templates/index.html +78 -0
- detectweb/templates/intros/intro_apple.html +155 -0
- detectweb/templates/intros/intro_cherry.html +190 -0
- detectweb/templates/intros/intro_corn.html +153 -0
.gitattributes
CHANGED
@@ -32,3 +32,33 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
32 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
33 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
34 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
33 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
34 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
35 |
+
demonstration/main.png filter=lfs diff=lfs merge=lfs -text
|
36 |
+
static/images/cherry/樱桃流胶病.png filter=lfs diff=lfs merge=lfs -text
|
37 |
+
static/images/cherry/樱桃叶斑病.png filter=lfs diff=lfs merge=lfs -text
|
38 |
+
static/usr_predict_images/user12/2020-05-17-16-33-48-D6SZEZJ4.jpg filter=lfs diff=lfs merge=lfs -text
|
39 |
+
static/usr_predict_images/user14/2017-01-15-16-33-48-AGP6Z4P1.jpg filter=lfs diff=lfs merge=lfs -text
|
40 |
+
static/usr_predict_images/user15/2019-01-15-19-33-48-HME4R1RO.jpg filter=lfs diff=lfs merge=lfs -text
|
41 |
+
static/usr_predict_images/user17/2016-02-11-19-33-48-NDZ9LMO2.jpg filter=lfs diff=lfs merge=lfs -text
|
42 |
+
static/usr_predict_images/user17/2020-04-11-18-33-48-JLTUBNHS.jpg filter=lfs diff=lfs merge=lfs -text
|
43 |
+
static/usr_predict_images/user18/2015-03-17-12-33-48-J6Y5FOXB.jpg filter=lfs diff=lfs merge=lfs -text
|
44 |
+
static/usr_predict_images/user18/2017-03-13-17-33-48-YPAI7D42.jpg filter=lfs diff=lfs merge=lfs -text
|
45 |
+
static/usr_predict_images/user18/2020-09-14-15-33-48-QU2V4IIE.jpg filter=lfs diff=lfs merge=lfs -text
|
46 |
+
static/usr_predict_images/user19/2015-05-13-12-33-48-DKHHZ74L.jpg filter=lfs diff=lfs merge=lfs -text
|
47 |
+
static/usr_predict_images/user19/2017-04-18-11-33-48-DDSAF3C8.jpg filter=lfs diff=lfs merge=lfs -text
|
48 |
+
static/usr_predict_images/user21/2015-01-15-16-33-48-VRJACV2V.jpg filter=lfs diff=lfs merge=lfs -text
|
49 |
+
static/usr_predict_images/user21/2019-07-13-11-33-48-W0U9908T.jpg filter=lfs diff=lfs merge=lfs -text
|
50 |
+
static/usr_predict_images/user22/2016-02-19-16-33-48-91NK6WSK.jpg filter=lfs diff=lfs merge=lfs -text
|
51 |
+
static/usr_predict_images/user23/2017-05-16-14-33-48-IA1I9J6U.jpg filter=lfs diff=lfs merge=lfs -text
|
52 |
+
static/usr_predict_images/user23/2021-08-12-13-33-48-BF4ZK6KZ.jpg filter=lfs diff=lfs merge=lfs -text
|
53 |
+
static/usr_predict_images/user24/2017-09-14-12-33-48-363A92FW.jpg filter=lfs diff=lfs merge=lfs -text
|
54 |
+
static/usr_predict_images/user24/2020-09-18-16-33-48-PXFE71QE.jpg filter=lfs diff=lfs merge=lfs -text
|
55 |
+
static/usr_predict_images/user27/2019-09-19-16-33-48-FCW52B4O.jpg filter=lfs diff=lfs merge=lfs -text
|
56 |
+
static/usr_predict_images/user29/2015-04-15-14-33-48-F66GCGAC.jpg filter=lfs diff=lfs merge=lfs -text
|
57 |
+
static/usr_predict_images/user29/2017-09-14-15-33-48-Y7XUUSPO.jpg filter=lfs diff=lfs merge=lfs -text
|
58 |
+
static/usr_predict_images/user3/2015-03-11-12-33-48-2OG4RNS2.jpg filter=lfs diff=lfs merge=lfs -text
|
59 |
+
static/usr_predict_images/user3/2018-02-14-16-33-48-ONIR7D0T.jpg filter=lfs diff=lfs merge=lfs -text
|
60 |
+
static/usr_predict_images/user3/2019-03-13-17-33-48-ER8GE0V7.jpg filter=lfs diff=lfs merge=lfs -text
|
61 |
+
static/usr_predict_images/user5/2018-04-17-14-33-48-YCL5BK3J.jpg filter=lfs diff=lfs merge=lfs -text
|
62 |
+
static/usr_predict_images/user6/2020-08-11-15-33-48-L5BC2VB9.jpg filter=lfs diff=lfs merge=lfs -text
|
63 |
+
static/usr_predict_images/user7/2020-04-15-11-33-48-MHBY92QC.jpg filter=lfs diff=lfs merge=lfs -text
|
64 |
+
static/usr_predict_images/user8/2020-09-14-11-33-48-0SODDSR8.jpg filter=lfs diff=lfs merge=lfs -text
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2021 Harry
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
README.md
CHANGED
@@ -1,10 +1,40 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# DetectWeb
|
2 |
+
中国农业大学毕业实习项目:病虫害检测,类别有苹果、樱桃、玉米、葡萄、桃子、胡椒、土豆、番茄等
|
3 |
+
|
4 |
+
China Agricultural University Graduation Internship: the purpose is to recognize the health condition of a fruit based on image. The dataset contains 8 types of fruit and 31 types of corrsponding conditions.
|
5 |
+
|
6 |
+
```
|
7 |
+
Apple = ['[Apple_scab]', '[Black_rot]', '[Cedar_apple_rust]', '[healthy]']
|
8 |
+
Cherry = ['[Powdery_mildew]', '[healthy]']
|
9 |
+
Corn = ['[Cercospora_leaf_spot] [Gray_leaf_spot]', '[Common_rust]', '[Northern_Leaf_Blight]', '[healthy]']
|
10 |
+
Grape = ['[Black_rot]', '[Esca_Black_Measles]', '[Leaf_blight]', '[healthy]']
|
11 |
+
Peach = ['[Bacterial_spot]', '[healthy]']
|
12 |
+
Pepper = ['[Bacterial_spot]', '[healthy]']
|
13 |
+
Potato = ['[Early_blight]', '[Late_blight]', '[healthy]']
|
14 |
+
Tomato = ['[Target_Spot]', '[YellowLeaf_Curl_Virus]', '[Bacterial_spot]', '[Early_blight]', '[healthy]', '[Late_blight]', '[Leaf_Mold]', '[Septoria_leaf_spot]', '[Spider_mites]']
|
15 |
+
```
|
16 |
+
|
17 |
+
We train a general model for all types of fruit, which means this model can be used to examine all 8 fruit and corresponding conditions. 8 specialized models for a single fruit are also trained for better recognition accuracy.
|
18 |
+
<img src="demonstration/kinds.png" width="60%">
|
19 |
+
|
20 |
+
## Software Environment
|
21 |
+
Project Framework:Flask + Bootstrap
|
22 |
+
|
23 |
+
Development Environment:Pycharm
|
24 |
+
|
25 |
+
Database:MySql
|
26 |
+
|
27 |
+
ORM library: SQLAlchemy
|
28 |
+
|
29 |
+
## Requirements
|
30 |
+
```
|
31 |
+
$ git clone https://github.com/lujiazho/DetectWeb.git
|
32 |
+
$ cd DetectWeb
|
33 |
+
$ pip install -r requirements.txt
|
34 |
+
```
|
35 |
+
|
36 |
+
## Demonstration
|
37 |
+
|Interface Ⅰ|Appearance|Interface Ⅱ|Appearance
|
38 |
+
|---|---|---|---
|
39 |
+
|<p align="center">Detection</p>|<img src="demonstration/detection.png" width="100%">|<p align="center">Main Interface</p>|<img src="demonstration/main.png" width="100%" alt="" align=center />
|
40 |
+
|<p align="center">Record</p>|<img src="demonstration/record.png" width="100%">|<p align="center">Trend</p>|<img src="demonstration/trend.png" width="100%" alt="" align=center />
|
demonstration/detection.png
ADDED
![]() |
demonstration/kinds.png
ADDED
![]() |
demonstration/main.png
ADDED
![]() |
Git LFS Details
|
demonstration/record.png
ADDED
![]() |
demonstration/trend.png
ADDED
![]() |
detectweb/__init__.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
https://devdocs.io/
|
3 |
+
https://codepen.io/
|
4 |
+
https://getbootstrap.com/
|
5 |
+
https://www.codeply.com/go
|
6 |
+
"""
|
7 |
+
from flask import Flask
|
8 |
+
from flask_sqlalchemy import SQLAlchemy
|
9 |
+
from flask_migrate import Migrate
|
10 |
+
from flask_login import LoginManager
|
11 |
+
from flask_mail import Mail
|
12 |
+
|
13 |
+
from detectweb.config import Config
|
14 |
+
|
15 |
+
db = SQLAlchemy()
|
16 |
+
migrate = Migrate()
|
17 |
+
# session管理
|
18 |
+
login_manager = LoginManager()
|
19 |
+
# 这条一加,访问index时就会自动跳转(重定向)到所赋值的那个函数去,即login
|
20 |
+
# 不过从index重定向到login会有额外参数“next=%2Findex”,这个%2F就代表了/index这个页面
|
21 |
+
login_manager.login_view = 'login'
|
22 |
+
# 邮件对象
|
23 |
+
mail = Mail()
|
24 |
+
|
25 |
+
from detectweb.route import index, login, logout, register, user, page_not_found, \
|
26 |
+
edit_profile, reset_password_request, password_reset, explore, user_activate, \
|
27 |
+
predict, feedback, dashboard, feedback_history, predict_history, predictbykind, \
|
28 |
+
visitor, predict_for_visitor, intro, article
|
29 |
+
|
30 |
+
|
31 |
+
def create_app():
|
32 |
+
app = Flask(__name__, static_folder='../static')
|
33 |
+
app.config.from_object(Config)
|
34 |
+
db.init_app(app) # sqlite数据库
|
35 |
+
migrate.init_app(app, db) # 数据库迭代
|
36 |
+
login_manager.init_app(app) # session管理
|
37 |
+
mail.init_app(app) # 初始化邮件服务
|
38 |
+
# 似乎这一行的第三个参数的index加不加都行
|
39 |
+
app.add_url_rule('/index', 'index', index, methods=['GET', 'POST'])
|
40 |
+
app.add_url_rule('/', 'index', index, methods=['GET', 'POST'])
|
41 |
+
app.add_url_rule('/login', 'login', login, methods=['GET', 'POST'])
|
42 |
+
app.add_url_rule('/visitor', 'visitor', visitor, methods=['GET', 'POST'])
|
43 |
+
app.add_url_rule('/logout', 'logout', logout)
|
44 |
+
app.add_url_rule('/register', 'register', register, methods=['GET', 'POST'])
|
45 |
+
app.add_url_rule('/predict', 'predict', predict, methods=['GET', 'POST'])
|
46 |
+
app.add_url_rule('/predictbykind', 'predictbykind', predictbykind, methods=['POST'])
|
47 |
+
app.add_url_rule('/predict_for_visitor', 'predict_for_visitor', predict_for_visitor, methods=['GET', 'POST'])
|
48 |
+
app.add_url_rule('/feedback', 'feedback', feedback, methods=['GET', 'POST'])
|
49 |
+
app.add_url_rule('/dashboard', 'dashboard', dashboard, methods=['GET'])
|
50 |
+
app.add_url_rule('/feedback_history', 'feedback_history', feedback_history, methods=['GET', 'POST'])
|
51 |
+
app.add_url_rule('/predict_history', 'predict_history', predict_history, methods=['GET', 'POST'])
|
52 |
+
# 第二个参数就是别名,比如这里的username,就可以url_for里填写profile
|
53 |
+
# 如果写url_for(user),就没法传username参数,也不知道该到那个user界面(其link为用户名)
|
54 |
+
app.add_url_rule('/<username>', 'profile', user, methods=['GET', 'POST'])
|
55 |
+
app.add_url_rule('/edit_profile', 'edit_profile', edit_profile, methods=['GET', 'POST'])
|
56 |
+
app.add_url_rule(
|
57 |
+
'/reset_password_request',
|
58 |
+
'reset_password_request',
|
59 |
+
reset_password_request,
|
60 |
+
methods=['GET', 'POST']
|
61 |
+
)
|
62 |
+
app.add_url_rule(
|
63 |
+
'/password_reset/<token>',
|
64 |
+
'password_reset',
|
65 |
+
password_reset,
|
66 |
+
methods=['GET', 'POST']
|
67 |
+
)
|
68 |
+
app.register_error_handler(404, page_not_found) # 加上这个,abort404的时候就会找这个函数
|
69 |
+
app.add_url_rule('/explore', 'explore', explore)
|
70 |
+
app.add_url_rule('/activate/<token>', 'user_activate', user_activate)
|
71 |
+
app.add_url_rule('/intro', 'intro', intro, methods=['GET'])
|
72 |
+
app.add_url_rule('/article', 'article', article, methods=['GET'])
|
73 |
+
return app
|
detectweb/__pycache__/__init__.cpython-37.pyc
ADDED
Binary file (2.42 kB). View file
|
|
detectweb/__pycache__/config.cpython-37.pyc
ADDED
Binary file (1.09 kB). View file
|
|
detectweb/__pycache__/email_.cpython-37.pyc
ADDED
Binary file (801 Bytes). View file
|
|
detectweb/__pycache__/forms.cpython-37.pyc
ADDED
Binary file (3.14 kB). View file
|
|
detectweb/__pycache__/label_image.cpython-37.pyc
ADDED
Binary file (3.36 kB). View file
|
|
detectweb/__pycache__/model.cpython-37.pyc
ADDED
Binary file (848 Bytes). View file
|
|
detectweb/__pycache__/route.cpython-37.pyc
ADDED
Binary file (14.5 kB). View file
|
|
detectweb/__pycache__/utils.cpython-37.pyc
ADDED
Binary file (9.6 kB). View file
|
|
detectweb/config.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
# 获取绝对路径
|
4 |
+
config_path = os.path.abspath(os.path.dirname(__file__))
|
5 |
+
|
6 |
+
|
7 |
+
class Config:
|
8 |
+
# 先找环境变量,若没有,则用默认的
|
9 |
+
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL", "sqlite:///" + os.path.join(config_path, 'detectweb.db'))
|
10 |
+
# 取消一个警告(暂不知什么用)
|
11 |
+
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
12 |
+
SECRET_KEY = os.environ.get('SECRET_KEY', 'a9087FFJFF9nnvc2@#$%FSD')
|
13 |
+
# 每页的tweet数
|
14 |
+
TWEET_PER_PAGE = os.environ.get('TWEET_PER_PAGE', 5)
|
15 |
+
# 每页predict数
|
16 |
+
PREDICT_PER_PAGE = os.environ.get('PREDICT_PER_PAGE', 5)
|
17 |
+
|
18 |
+
# 因为有了这个默认的sender,就不需要写sender了,这个参数必须要配置
|
19 |
+
MAIL_DEFAULT_SENDER = os.environ.get('MAIL_DEFAULT_SENDER', '[email protected]')
|
20 |
+
MAIL_SERVER = os.environ.get('MAIL_SERVER', 'smtp.qq.com')
|
21 |
+
MAIL_PORT = os.environ.get('MAIL_PORT', 587)
|
22 |
+
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS', True)
|
23 |
+
MAIL_USERNAME = os.environ.get('MAIL_USERNAME', '[email protected]')
|
24 |
+
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD', 'password')
|
25 |
+
# 用于邮件subject
|
26 |
+
MAIL_SUBJECT_RESET_PASSWORD = '[DetectWeb] Please Reset Your Password'
|
27 |
+
# 用于邮件激活
|
28 |
+
MAIN_SUBJECT_USER_ACTIVATE = '[DetectWeb] Please Activate Your Accout'
|
detectweb/detectweb.db
ADDED
Binary file (311 kB). View file
|
|
detectweb/email_.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from threading import Thread
|
2 |
+
|
3 |
+
from flask import current_app
|
4 |
+
from flask_mail import Message
|
5 |
+
from detectweb import mail
|
6 |
+
|
7 |
+
# 异步发送邮件函数
|
8 |
+
def send_async_email(app, msg):
|
9 |
+
with app.app_context():
|
10 |
+
mail.send(msg)
|
11 |
+
|
12 |
+
|
13 |
+
def send_email(subject, recipients, text_body, html_body):
|
14 |
+
# subject主题,接收者,
|
15 |
+
msg = Message(
|
16 |
+
subject=subject,
|
17 |
+
recipients=recipients,
|
18 |
+
reply_to='[email protected]' # 不写sender而写reply_to,使得收到的邮件都被这个邮箱自动删除
|
19 |
+
)
|
20 |
+
# 文本body
|
21 |
+
msg.body = text_body
|
22 |
+
# 看收到邮件的客户端,如果不支持html格式显示,那就用text显示
|
23 |
+
msg.html = html_body
|
24 |
+
# 多线程发送,为了点击发送邮件后不卡住,大概会卡住3-4秒等待邮件去发
|
25 |
+
Thread(
|
26 |
+
target=send_async_email,
|
27 |
+
args=(current_app._get_current_object(), msg)).start()
|
detectweb/forms.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask_wtf import FlaskForm
|
2 |
+
from wtforms import StringField, PasswordField, BooleanField, SubmitField, \
|
3 |
+
TextAreaField
|
4 |
+
from wtforms.validators import DataRequired, Email, EqualTo, ValidationError, \
|
5 |
+
Length
|
6 |
+
|
7 |
+
from detectweb.models.user import User
|
8 |
+
|
9 |
+
|
10 |
+
class LoginForm(FlaskForm):
|
11 |
+
# 不知道为啥不设置为False就出问题
|
12 |
+
class Meta:
|
13 |
+
csrf = False
|
14 |
+
username = StringField("Username", validators=[DataRequired()])
|
15 |
+
password = PasswordField("Password", validators=[DataRequired()])
|
16 |
+
remember_me = BooleanField("保持登陆状态")
|
17 |
+
submit = SubmitField('Sign In')
|
18 |
+
|
19 |
+
|
20 |
+
class RegisterForm(FlaskForm):
|
21 |
+
username = StringField("用户名", validators=[DataRequired()])
|
22 |
+
email = StringField("邮箱", validators=[DataRequired(), Email()])
|
23 |
+
password = PasswordField("密码", validators=[DataRequired()])
|
24 |
+
password2 = PasswordField(
|
25 |
+
"重复密码", validators=[DataRequired(), EqualTo('password')])
|
26 |
+
submit = SubmitField('Register')
|
27 |
+
|
28 |
+
def validate_username(self, username):
|
29 |
+
user = User.query.filter_by(username=username.data).first()
|
30 |
+
if user is not None:
|
31 |
+
raise ValidationError('please use different username')
|
32 |
+
|
33 |
+
def validate_email(self, email):
|
34 |
+
user = User.query.filter_by(email=email.data).first()
|
35 |
+
if user is not None:
|
36 |
+
raise ValidationError('please use different email address')
|
37 |
+
|
38 |
+
|
39 |
+
class EditProfileForm(FlaskForm):
|
40 |
+
about_me = TextAreaField('About me', validators=[Length(min=0, max=120)])
|
41 |
+
submit = SubmitField('Save')
|
42 |
+
|
43 |
+
|
44 |
+
class TweetForm(FlaskForm):
|
45 |
+
tweet = TextAreaField('Tweet', validators=[DataRequired(), Length(min=0, max=140)])
|
46 |
+
submit = SubmitField('Tweet')
|
47 |
+
|
48 |
+
# 输入邮箱请求重置密码
|
49 |
+
class PasswdResetRequestForm(FlaskForm):
|
50 |
+
email = StringField("电子邮箱", validators=[DataRequired(), Email()])
|
51 |
+
submit = SubmitField('Reset Password')
|
52 |
+
|
53 |
+
def validate_email(self, email):
|
54 |
+
user = User.query.filter_by(email=email.data).first()
|
55 |
+
if not user:
|
56 |
+
raise ValidationError(
|
57 |
+
'You do not have an account for this email address')
|
58 |
+
|
59 |
+
# 重置密码
|
60 |
+
class PasswdResetForm(FlaskForm):
|
61 |
+
password = PasswordField("密码", validators=[DataRequired()])
|
62 |
+
password2 = PasswordField(
|
63 |
+
"重复密码", validators=[DataRequired(), EqualTo('password')])
|
64 |
+
submit = SubmitField('Submit')
|
detectweb/label_image.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
|
2 |
+
#
|
3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4 |
+
# you may not use this file except in compliance with the License.
|
5 |
+
# You may obtain a copy of the License at
|
6 |
+
#
|
7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8 |
+
#
|
9 |
+
# Unless required by applicable law or agreed to in writing, software
|
10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
+
# See the License for the specific language governing permissions and
|
13 |
+
# limitations under the License.
|
14 |
+
# ==============================================================================
|
15 |
+
|
16 |
+
from __future__ import absolute_import
|
17 |
+
from __future__ import division
|
18 |
+
from __future__ import print_function
|
19 |
+
|
20 |
+
import argparse
|
21 |
+
import sys
|
22 |
+
import time
|
23 |
+
|
24 |
+
import numpy as np
|
25 |
+
import tensorflow as tf
|
26 |
+
# import tensorflow.compat.v1 as tf
|
27 |
+
# tf.compat.v1.disable_eager_execution()
|
28 |
+
|
29 |
+
def load_graph(model_file):
|
30 |
+
graph = tf.Graph()
|
31 |
+
graph_def = tf.compat.v1.GraphDef()
|
32 |
+
|
33 |
+
with open(model_file, "rb") as f:
|
34 |
+
graph_def.ParseFromString(f.read())
|
35 |
+
with graph.as_default():
|
36 |
+
tf.import_graph_def(graph_def)
|
37 |
+
|
38 |
+
return graph
|
39 |
+
|
40 |
+
def read_tensor_from_image_file(file_name, input_height=299, input_width=299,
|
41 |
+
input_mean=0, input_std=255):
|
42 |
+
input_name = "file_reader"
|
43 |
+
output_name = "normalized"
|
44 |
+
file_reader = tf.read_file(file_name, input_name)
|
45 |
+
if file_name.endswith(".png"):
|
46 |
+
image_reader = tf.image.decode_png(file_reader, channels = 3,
|
47 |
+
name='png_reader')
|
48 |
+
elif file_name.endswith(".gif"):
|
49 |
+
image_reader = tf.squeeze(tf.image.decode_gif(file_reader,
|
50 |
+
name='gif_reader'))
|
51 |
+
elif file_name.endswith(".bmp"):
|
52 |
+
image_reader = tf.image.decode_bmp(file_reader, name='bmp_reader')
|
53 |
+
else:
|
54 |
+
image_reader = tf.image.decode_jpeg(file_reader, channels = 3,
|
55 |
+
name='jpeg_reader')
|
56 |
+
float_caster = tf.cast(image_reader, tf.float32)
|
57 |
+
dims_expander = tf.expand_dims(float_caster, 0);
|
58 |
+
resized = tf.image.resize_bilinear(dims_expander, [input_height, input_width])
|
59 |
+
normalized = tf.divide(tf.subtract(resized, [input_mean]), [input_std])
|
60 |
+
sess = tf.Session()
|
61 |
+
result = sess.run(normalized)
|
62 |
+
|
63 |
+
return result
|
64 |
+
|
65 |
+
def load_labels(label_file):
|
66 |
+
label = []
|
67 |
+
proto_as_ascii_lines = tf.gfile.GFile(label_file).readlines()
|
68 |
+
for l in proto_as_ascii_lines:
|
69 |
+
label.append(l.rstrip())
|
70 |
+
return label
|
71 |
+
|
72 |
+
if __name__ == "__main__":
|
73 |
+
file_name = "tf_files/flower_photos/daisy/3475870145_685a19116d.jpg"
|
74 |
+
model_file = "tf_files/retrained_graph.pb"
|
75 |
+
label_file = "tf_files/retrained_labels.txt"
|
76 |
+
input_height = 224
|
77 |
+
input_width = 224
|
78 |
+
input_mean = 128
|
79 |
+
input_std = 128
|
80 |
+
input_layer = "input"
|
81 |
+
output_layer = "final_result"
|
82 |
+
|
83 |
+
parser = argparse.ArgumentParser()
|
84 |
+
parser.add_argument("--image", help="image to be processed")
|
85 |
+
parser.add_argument("--graph", help="graph/model to be executed")
|
86 |
+
parser.add_argument("--labels", help="name of file containing labels")
|
87 |
+
parser.add_argument("--input_height", type=int, help="input height")
|
88 |
+
parser.add_argument("--input_width", type=int, help="input width")
|
89 |
+
parser.add_argument("--input_mean", type=int, help="input mean")
|
90 |
+
parser.add_argument("--input_std", type=int, help="input std")
|
91 |
+
parser.add_argument("--input_layer", help="name of input layer")
|
92 |
+
parser.add_argument("--output_layer", help="name of output layer")
|
93 |
+
args = parser.parse_args()
|
94 |
+
|
95 |
+
if args.graph:
|
96 |
+
model_file = args.graph
|
97 |
+
if args.image:
|
98 |
+
file_name = args.image
|
99 |
+
if args.labels:
|
100 |
+
label_file = args.labels
|
101 |
+
if args.input_height:
|
102 |
+
input_height = args.input_height
|
103 |
+
if args.input_width:
|
104 |
+
input_width = args.input_width
|
105 |
+
if args.input_mean:
|
106 |
+
input_mean = args.input_mean
|
107 |
+
if args.input_std:
|
108 |
+
input_std = args.input_std
|
109 |
+
if args.input_layer:
|
110 |
+
input_layer = args.input_layer
|
111 |
+
if args.output_layer:
|
112 |
+
output_layer = args.output_layer
|
113 |
+
|
114 |
+
graph = load_graph(model_file)
|
115 |
+
t = read_tensor_from_image_file(file_name,
|
116 |
+
input_height=input_height,
|
117 |
+
input_width=input_width,
|
118 |
+
input_mean=input_mean,
|
119 |
+
input_std=input_std)
|
120 |
+
|
121 |
+
input_name = "import/" + input_layer
|
122 |
+
output_name = "import/" + output_layer
|
123 |
+
input_operation = graph.get_operation_by_name(input_name);
|
124 |
+
output_operation = graph.get_operation_by_name(output_name);
|
125 |
+
|
126 |
+
with tf.Session(graph=graph) as sess:
|
127 |
+
start = time.time()
|
128 |
+
results = sess.run(output_operation.outputs[0],
|
129 |
+
{input_operation.outputs[0]: t})
|
130 |
+
end=time.time()
|
131 |
+
results = np.squeeze(results)
|
132 |
+
|
133 |
+
top_k = results.argsort()[-5:][::-1]
|
134 |
+
labels = load_labels(label_file)
|
135 |
+
|
136 |
+
print('\nEvaluation time (1-image): {:.3f}s\n'.format(end-start))
|
137 |
+
template = "{} (score={:0.5f})"
|
138 |
+
for i in top_k:
|
139 |
+
print(template.format(labels[i], results[i]))
|
detectweb/model.py
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
import time
|
3 |
+
import io
|
4 |
+
import os
|
5 |
+
|
6 |
+
import random
|
7 |
+
import string
|
8 |
+
import datetime
|
9 |
+
|
10 |
+
import base64
|
11 |
+
from PIL import Image, ImageFile
|
12 |
+
|
13 |
+
from flask import request, jsonify, Flask, url_for
|
14 |
+
|
15 |
+
import numpy as np
|
16 |
+
import tensorflow as tf
|
17 |
+
# import tensorflow.compat.v1 as tf
|
18 |
+
# tf.compat.v1.disable_eager_execution()
|
19 |
+
|
20 |
+
from detectweb import label_image
|
21 |
+
|
22 |
+
model_file = 'static/tf_files/retrained_graph.pb'
|
23 |
+
label_file = 'static/tf_files/retrained_labels.txt'
|
24 |
+
input_height = 224
|
25 |
+
input_width = 224
|
26 |
+
input_mean = 128
|
27 |
+
input_std = 128
|
28 |
+
input_layer = "input"
|
29 |
+
output_layer = "final_result"
|
30 |
+
|
31 |
+
g = tf.Graph()
|
32 |
+
with g.as_default():
|
33 |
+
graph = label_image.load_graph(model_file)
|
34 |
+
|
detectweb/models/__init__.py
ADDED
File without changes
|
detectweb/models/__pycache__/__init__.cpython-37.pyc
ADDED
Binary file (150 Bytes). View file
|
|
detectweb/models/__pycache__/predict.cpython-37.pyc
ADDED
Binary file (1.01 kB). View file
|
|
detectweb/models/__pycache__/tweet.cpython-37.pyc
ADDED
Binary file (838 Bytes). View file
|
|
detectweb/models/__pycache__/user.cpython-37.pyc
ADDED
Binary file (3.89 kB). View file
|
|
detectweb/models/predict.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from datetime import datetime
|
2 |
+
from detectweb import db
|
3 |
+
|
4 |
+
|
5 |
+
class Predict(db.Model):
|
6 |
+
id = db.Column(db.Integer, primary_key=True)
|
7 |
+
# 理论上imgname可能相同,实际上几乎不可能,因此认为unique
|
8 |
+
img_name = db.Column(db.String(64), unique=True, index=True)
|
9 |
+
img_path = db.Column(db.String(128))
|
10 |
+
size = db.Column(db.String(20))
|
11 |
+
predict_time = db.Column(db.DateTime, default=datetime.utcnow)
|
12 |
+
predict_result = db.Column(db.String(64))
|
13 |
+
predict_value = db.Column(db.String(20))
|
14 |
+
# 这个user是小写,代表table的名字(默认情况下,table名字为小写的class)
|
15 |
+
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
16 |
+
|
17 |
+
def __repr__(self):
|
18 |
+
return "id={}, img={}, path={}, body={}, create_time={}, result={}, user_id={}".format(
|
19 |
+
self.id, self.img_name, self.img_path, self.size, self.predict_time, self.predict_result, self.user_id
|
20 |
+
)
|
detectweb/models/tweet.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from datetime import datetime
|
2 |
+
|
3 |
+
from detectweb import db
|
4 |
+
|
5 |
+
|
6 |
+
class Tweet(db.Model):
|
7 |
+
id = db.Column(db.Integer, primary_key=True)
|
8 |
+
img = db.Column(db.String(64))
|
9 |
+
body = db.Column(db.String(140))
|
10 |
+
create_time = db.Column(db.DateTime, default=datetime.utcnow)
|
11 |
+
# 这个user是小写,代表table的名字(默认情况下,table名字为小写的class)
|
12 |
+
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
13 |
+
|
14 |
+
def __repr__(self):
|
15 |
+
return "id={}, img={}, body={}, create_time={}, user_id={}".format(
|
16 |
+
self.id, self.img, self.body, self.create_time, self.user_id
|
17 |
+
)
|
detectweb/models/user.py
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from datetime import datetime
|
2 |
+
from hashlib import md5
|
3 |
+
import time
|
4 |
+
|
5 |
+
from werkzeug.security import generate_password_hash, check_password_hash
|
6 |
+
# 提供关于用户session管理方法
|
7 |
+
from flask_login import UserMixin
|
8 |
+
from flask import current_app
|
9 |
+
import jwt
|
10 |
+
|
11 |
+
from detectweb import db, login_manager
|
12 |
+
from detectweb.models.tweet import Tweet
|
13 |
+
from detectweb.models.predict import Predict
|
14 |
+
|
15 |
+
# 没有建立类,因为这个表只描述关系,两个column都只存储了ForeignKey
|
16 |
+
followers = db.Table('followers',
|
17 |
+
db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
|
18 |
+
db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
|
19 |
+
)
|
20 |
+
|
21 |
+
|
22 |
+
class User(UserMixin, db.Model):
|
23 |
+
id = db.Column(db.Integer, primary_key=True)
|
24 |
+
username = db.Column(db.String(64), unique=True, index=True)
|
25 |
+
email = db.Column(db.String(64), unique=True, index=True)
|
26 |
+
country = db.Column(db.String(20))
|
27 |
+
province = db.Column(db.String(20))
|
28 |
+
city = db.Column(db.String(20))
|
29 |
+
password_hash = db.Column(db.String(128))
|
30 |
+
about_me = db.Column(db.String(120))
|
31 |
+
create_time = db.Column(db.DateTime, default=datetime.utcnow)
|
32 |
+
is_activated = db.Column(db.Boolean, default=False)
|
33 |
+
|
34 |
+
# 这不是一个column,和Tweet这个class建立关系,属于一对多,一个user多个tweets
|
35 |
+
tweets = db.relationship('Tweet', backref='author', lazy='dynamic')
|
36 |
+
predicts = db.relationship('Predict', backref='author', lazy='dynamic')
|
37 |
+
|
38 |
+
# 这个关系创建后,单个user中的followed变量就代表了自己关注的人u1.followed.append(u3)就表示u1关注u3
|
39 |
+
# followers就代表了关注自己的人
|
40 |
+
followed = db.relationship(
|
41 |
+
'User', secondary=followers,
|
42 |
+
primaryjoin=(followers.c.follower_id == id), # 通过这个找到自己关注了几个人
|
43 |
+
secondaryjoin=(followers.c.followed_id == id), # 被多少人关注
|
44 |
+
backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')
|
45 |
+
|
46 |
+
def __repr__(self):
|
47 |
+
return 'id={}, username={}, email={}, password_hash={}'.format(
|
48 |
+
self.id, self.username, self.email, self.password_hash
|
49 |
+
)
|
50 |
+
|
51 |
+
def set_password(self, password):
|
52 |
+
self.password_hash = generate_password_hash(password)
|
53 |
+
|
54 |
+
def check_password(self, password):
|
55 |
+
return check_password_hash(self.password_hash, password)
|
56 |
+
|
57 |
+
# 动态生成头像
|
58 |
+
def avatar(self, size=80):
|
59 |
+
md5_digest = md5(self.email.lower().encode('utf-8')).hexdigest()
|
60 |
+
return 'https://cdn.v2ex.com/gravatar/{}?d=identicon&s={}'.format(
|
61 |
+
md5_digest, size)
|
62 |
+
|
63 |
+
# 关注
|
64 |
+
def follow(self, user):
|
65 |
+
if not self.is_following(user):
|
66 |
+
self.followed.append(user)
|
67 |
+
|
68 |
+
# 取关
|
69 |
+
def unfollow(self, user):
|
70 |
+
if self.is_following(user):
|
71 |
+
self.followed.remove(user)
|
72 |
+
|
73 |
+
# 返回user是否是自己正关注的人
|
74 |
+
def is_following(self, user):
|
75 |
+
return self.followed.filter(
|
76 |
+
followers.c.followed_id == user.id).count() > 0
|
77 |
+
|
78 |
+
# 自己的以及关注的人的tweet
|
79 |
+
def own_and_followed_tweets(self):
|
80 |
+
# 把tweet和followers两张表join在一起,条件是join的第二个参数,合起来就是[谁,关注了谁,被关注人的tweet,...]
|
81 |
+
# 然后进行filter,我只关心我关注的,即follower_id是我的id
|
82 |
+
followed = Tweet.query.join(
|
83 |
+
followers, (followers.c.followed_id == Tweet.user_id)).filter(
|
84 |
+
followers.c.follower_id == self.id)
|
85 |
+
own = Tweet.query.filter_by(user_id=self.id)
|
86 |
+
# 然后把这两个表union起来,按时间降排序(最新的在前面)
|
87 |
+
return followed.union(own).order_by(Tweet.create_time.desc())
|
88 |
+
|
89 |
+
# jwt为java web token
|
90 |
+
def get_jwt(self, expire=7200):
|
91 |
+
return jwt.encode(
|
92 |
+
{
|
93 |
+
'email': self.email, # 键值对,email
|
94 |
+
'exp': time.time() + expire # 键值对,expire时间,7200秒代表两个小时,不过verify时并没有检查是否过期
|
95 |
+
},
|
96 |
+
current_app.config['SECRET_KEY'], # secret码
|
97 |
+
algorithm='HS256' # 算法
|
98 |
+
).decode('utf-8') # 如果不加decode就是个binary string
|
99 |
+
|
100 |
+
"""
|
101 |
+
想直接通过User class来使用,而不是先实例化一个
|
102 |
+
"""
|
103 |
+
@staticmethod
|
104 |
+
def verify_jwt(token):
|
105 |
+
# 用户点击链接后,服务端验证token是否合法
|
106 |
+
try:
|
107 |
+
email = jwt.decode(
|
108 |
+
token,
|
109 |
+
current_app.config['SECRET_KEY'],
|
110 |
+
algorithms=['HS256']
|
111 |
+
)
|
112 |
+
email = email['email']
|
113 |
+
except:
|
114 |
+
return
|
115 |
+
# 返回合法的用户
|
116 |
+
return User.query.filter_by(email=email).first()
|
117 |
+
|
118 |
+
# 根据文档提供的方法,为了session管理
|
119 |
+
@login_manager.user_loader
|
120 |
+
def load_user(id):
|
121 |
+
return User.query.get(int(id))
|
122 |
+
|
123 |
+
"""
|
124 |
+
国内Gravatar镜像源收集
|
125 |
+
gravatar官方的www https://www.gravatar.com/avatar/
|
126 |
+
gravatar官方的cn https://cn.gravatar.com/avatar/
|
127 |
+
gravatar官方的en https://en.gravatar.com/avatar/
|
128 |
+
gravatar官方的secure https://secure.gravatar.com/avatar/
|
129 |
+
V2EX https://cdn.v2ex.com/gravatar/
|
130 |
+
Loli https://gravatar.loli.net/avatar/
|
131 |
+
极客族 https://sdn.geekzu.org/avatar/
|
132 |
+
Zeruns's Blog:https://gravatar.zeruns.tech/avatar/
|
133 |
+
宝硕博客:https://gravatar.baoshuo.ren/avatar
|
134 |
+
左岸博客源:https://avatar.zrahh.com/avatar
|
135 |
+
"""
|
detectweb/route.py
ADDED
@@ -0,0 +1,546 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from flask import render_template, redirect, url_for, request, \
|
2 |
+
abort, current_app, flash
|
3 |
+
from flask_login import login_user, current_user, logout_user, login_required
|
4 |
+
from sqlalchemy import and_
|
5 |
+
|
6 |
+
from detectweb.forms import LoginForm, RegisterForm, EditProfileForm, TweetForm, \
|
7 |
+
PasswdResetRequestForm, PasswdResetForm
|
8 |
+
from detectweb.models.user import User, load_user
|
9 |
+
from detectweb.models.tweet import Tweet
|
10 |
+
from detectweb.models.predict import Predict
|
11 |
+
from detectweb import db, utils
|
12 |
+
from detectweb.email_ import send_email
|
13 |
+
from detectweb.model import *
|
14 |
+
|
15 |
+
# 加上了login_required,页面就能被保护,需要先登录
|
16 |
+
@login_required
|
17 |
+
def index():
|
18 |
+
# # 获取page参数,或者等于1,即默认就是显示第一页
|
19 |
+
# page_num = int(request.args.get('page') or 1)
|
20 |
+
# # index的tweet是自己+关注人的
|
21 |
+
# tweets = current_user.own_and_followed_tweets().paginate(
|
22 |
+
# page=page_num, per_page=current_app.config['TWEET_PER_PAGE'], error_out=False)
|
23 |
+
#
|
24 |
+
# # tweets.next_num获取下一页的number,前提是还有下一页
|
25 |
+
# next_url = url_for('index', page=tweets.next_num) if tweets.has_next else None
|
26 |
+
# prev_url = url_for('index', page=tweets.prev_num) if tweets.has_prev else None
|
27 |
+
# return render_template(
|
28 |
+
# 'index.html', tweets=tweets.items, next_url=next_url, prev_url=prev_url
|
29 |
+
# )
|
30 |
+
return render_template('index.html')
|
31 |
+
|
32 |
+
|
33 |
+
def login():
|
34 |
+
# session管理
|
35 |
+
if current_user.is_authenticated:
|
36 |
+
return redirect(url_for('index'))
|
37 |
+
form = LoginForm()
|
38 |
+
# 表示如果是点击submit触发的该函数
|
39 |
+
if form.validate_on_submit():
|
40 |
+
u = User.query.filter_by(username=form.username.data).first()
|
41 |
+
if u is None or not u.check_password(form.password.data):
|
42 |
+
flash('非法用户名或密码', 'danger')
|
43 |
+
return redirect(url_for('login'))
|
44 |
+
# remember_me用于session管理,而不是记住用户名
|
45 |
+
login_user(u, remember=form.remember_me.data)
|
46 |
+
next_page = request.args.get('next')
|
47 |
+
if next_page: # 是否来自于跳转登录,如果是,那就返回到用户一开始点的那个页面去
|
48 |
+
return redirect(next_page)
|
49 |
+
return redirect(url_for('index')) # url_for通过函数名来找
|
50 |
+
return render_template('login.html', title="Sign In", form=form)
|
51 |
+
|
52 |
+
def visitor():
|
53 |
+
random_username = "visitor"+''.join(random.choice(string.digits) for _ in range(8))
|
54 |
+
ip = request.remote_addr
|
55 |
+
addr = utils.getAddrFromIP(ip)
|
56 |
+
user = User(
|
57 |
+
username=random_username,
|
58 |
+
email=utils.RandomEmail(),
|
59 |
+
country=addr["ct"],
|
60 |
+
city=addr["city"],
|
61 |
+
province=addr["prov"]
|
62 |
+
)
|
63 |
+
user.is_visitor = True
|
64 |
+
# login_user(user)
|
65 |
+
return render_template('index.html', current_user=user)
|
66 |
+
|
67 |
+
def logout():
|
68 |
+
logout_user()
|
69 |
+
return redirect(url_for('login'))
|
70 |
+
|
71 |
+
|
72 |
+
def register():
|
73 |
+
# 如果是已登录状态,则直接返回index页面,不让注册
|
74 |
+
if current_user.is_authenticated:
|
75 |
+
return redirect(url_for('index'))
|
76 |
+
form = RegisterForm()
|
77 |
+
if form.validate_on_submit():
|
78 |
+
# 获取ip
|
79 |
+
ip = request.remote_addr
|
80 |
+
print(ip)
|
81 |
+
addr = utils.getAddrFromIP(ip)
|
82 |
+
print(addr)
|
83 |
+
# 创建表
|
84 |
+
user = User(
|
85 |
+
username=form.username.data,
|
86 |
+
email=form.email.data,
|
87 |
+
country=addr["ct"],
|
88 |
+
city=addr["city"],
|
89 |
+
province=addr["prov"]
|
90 |
+
)
|
91 |
+
user.set_password(form.password.data)
|
92 |
+
db.session.add(user)
|
93 |
+
db.session.commit()
|
94 |
+
return redirect(url_for('login'))
|
95 |
+
return render_template('register.html', title='Registration', form=form)
|
96 |
+
|
97 |
+
@login_required
|
98 |
+
def user(username):
|
99 |
+
u = User.query.filter_by(username=username).first()
|
100 |
+
if u is None: # 用户不存在,返回404
|
101 |
+
abort(404)
|
102 |
+
|
103 |
+
if request.method == 'POST':
|
104 |
+
if request.form['request_button'] == 'Follow':
|
105 |
+
current_user.follow(u)
|
106 |
+
db.session.commit()
|
107 |
+
elif request.form['request_button'] == "Unfollow":
|
108 |
+
current_user.unfollow(u)
|
109 |
+
db.session.commit()
|
110 |
+
else:
|
111 |
+
flash("邮件已发送, 请查看!", 'info')
|
112 |
+
send_email_for_user_activate(current_user)
|
113 |
+
return render_template('user.html', title='Profile', user=u)
|
114 |
+
|
115 |
+
|
116 |
+
# 生成url并发送邮件
|
117 |
+
def send_email_for_user_activate(user):
|
118 |
+
|
119 |
+
token = user.get_jwt()
|
120 |
+
url_user_activate = url_for(
|
121 |
+
'user_activate',
|
122 |
+
token=token,
|
123 |
+
_external=True
|
124 |
+
)
|
125 |
+
send_email(
|
126 |
+
subject=current_app.config['MAIN_SUBJECT_USER_ACTIVATE'],
|
127 |
+
recipients=[user.email],
|
128 |
+
text_body= render_template(
|
129 |
+
'email/user_activate.txt',
|
130 |
+
username=user.username,
|
131 |
+
url_user_activate=url_user_activate
|
132 |
+
),
|
133 |
+
html_body=render_template(
|
134 |
+
'email/user_activate.html',
|
135 |
+
username=user.username,
|
136 |
+
url_user_activate=url_user_activate
|
137 |
+
)
|
138 |
+
)
|
139 |
+
|
140 |
+
# 点击链接后进入该函数激活
|
141 |
+
def user_activate(token):
|
142 |
+
# # 这一句为作者误写,如果加了永远都激活不了
|
143 |
+
# if current_user.is_authenticated:
|
144 |
+
# return redirect(url_for('index'))
|
145 |
+
user = User.verify_jwt(token)
|
146 |
+
if not user: # 如果没找到,其实不是expire了,因为没有判断是否expire,同一个链接永远都可以用,只能说明token是伪造的
|
147 |
+
msg = "Token已过期d, 请尝试重新发送文件"
|
148 |
+
else:
|
149 |
+
user.is_activated = True
|
150 |
+
db.session.commit()
|
151 |
+
msg = '用户已激活!'
|
152 |
+
return render_template(
|
153 |
+
'user_activate.html', msg=msg
|
154 |
+
)
|
155 |
+
|
156 |
+
|
157 |
+
def page_not_found(e):
|
158 |
+
return render_template('404.html'), 404
|
159 |
+
|
160 |
+
|
161 |
+
@login_required
|
162 |
+
def edit_profile():
|
163 |
+
form = EditProfileForm()
|
164 |
+
if request.method == 'GET':
|
165 |
+
form.about_me.data = current_user.about_me # 显示原来的
|
166 |
+
if form.validate_on_submit():
|
167 |
+
current_user.about_me = form.about_me.data # 赋值
|
168 |
+
db.session.commit() # 提交
|
169 |
+
# 跳转
|
170 |
+
return redirect(url_for('profile', username=current_user.username))
|
171 |
+
return render_template('edit_profile.html', form=form)
|
172 |
+
|
173 |
+
|
174 |
+
def reset_password_request():
|
175 |
+
# 如果已处于登录状态,就不需要重置密码了
|
176 |
+
if current_user.is_authenticated:
|
177 |
+
return redirect(url_for('index'))
|
178 |
+
# 初始化这个form
|
179 |
+
form = PasswdResetRequestForm()
|
180 |
+
if form.validate_on_submit():
|
181 |
+
user = User.query.filter_by(email=form.email.data).first()
|
182 |
+
if user:
|
183 |
+
flash(
|
184 |
+
"你将很快收到一封邮件,你能借此重置你的密码。 \
|
185 |
+
如果没有收到,请检查垃圾箱。", 'info'
|
186 |
+
)
|
187 |
+
# 用户请求的时候,服务器生成token
|
188 |
+
token = user.get_jwt()
|
189 |
+
# 生成reset密码的url
|
190 |
+
url_password_reset = url_for(
|
191 |
+
'password_reset',
|
192 |
+
token=token,
|
193 |
+
_external=True # 表示是完整的http链接:ip 端口 以及后面的url
|
194 |
+
)
|
195 |
+
url_password_reset_request = url_for(
|
196 |
+
'reset_password_request',
|
197 |
+
_external=True
|
198 |
+
)
|
199 |
+
send_email(
|
200 |
+
subject=current_app.config['MAIL_SUBJECT_RESET_PASSWORD'], # 主题
|
201 |
+
recipients=[user.email], # 接收者
|
202 |
+
text_body= render_template(
|
203 |
+
'email/passwd_reset.txt',
|
204 |
+
url_password_reset=url_password_reset, # 传入url
|
205 |
+
url_password_reset_request=url_password_reset_request
|
206 |
+
),
|
207 |
+
html_body=render_template(
|
208 |
+
'email/passwd_reset.html',
|
209 |
+
url_password_reset=url_password_reset,
|
210 |
+
url_password_reset_request=url_password_reset_request
|
211 |
+
)
|
212 |
+
)
|
213 |
+
# 重置完了就返回登录页面
|
214 |
+
return redirect(url_for('login'))
|
215 |
+
return render_template('password_reset_request.html', form=form)
|
216 |
+
|
217 |
+
|
218 |
+
def password_reset(token):
|
219 |
+
# 已经登录的情况下,同样不需要reset
|
220 |
+
if current_user.is_authenticated:
|
221 |
+
return redirect(url_for('index'))
|
222 |
+
# 先验证,然后根据token返回一个user,然后对这个user的密码进行重置
|
223 |
+
user = User.verify_jwt(token)
|
224 |
+
if not user:
|
225 |
+
# 重定向到login
|
226 |
+
return redirect(url_for('login'))
|
227 |
+
# 重置密码的form
|
228 |
+
form = PasswdResetForm()
|
229 |
+
# 提交后就覆盖之前的密码
|
230 |
+
if form.validate_on_submit():
|
231 |
+
user.set_password(form.password.data)
|
232 |
+
db.session.commit()
|
233 |
+
# 重定向login
|
234 |
+
return redirect(url_for('login'))
|
235 |
+
return render_template(
|
236 |
+
'password_reset.html', title='Password Reset', form=form
|
237 |
+
)
|
238 |
+
|
239 |
+
|
240 |
+
@login_required
|
241 |
+
def explore():
|
242 |
+
# get all user and sort by followers
|
243 |
+
page_num = request.args.get('page') or "1"
|
244 |
+
if page_num.isdigit():
|
245 |
+
page_num = int(page_num)
|
246 |
+
else:
|
247 |
+
abort(404)
|
248 |
+
tweets = Tweet.query.order_by(Tweet.create_time.desc()).paginate(
|
249 |
+
page=page_num, per_page=current_app.config['TWEET_PER_PAGE'], error_out=False)
|
250 |
+
|
251 |
+
next_url = url_for('explore', page=tweets.next_num) if tweets.has_next else None
|
252 |
+
prev_url = url_for('explore', page=tweets.prev_num) if tweets.has_prev else None
|
253 |
+
return render_template(
|
254 |
+
'explore.html', tweets=tweets.items, next_url=next_url, prev_url=prev_url
|
255 |
+
)
|
256 |
+
|
257 |
+
@login_required
|
258 |
+
def predict_history():
|
259 |
+
u = User.query.filter_by(username=current_user.username).first()
|
260 |
+
|
261 |
+
# 默认第一页
|
262 |
+
page_num = request.args.get('page') or "1"
|
263 |
+
if page_num.isdigit():
|
264 |
+
page_num = int(page_num)
|
265 |
+
else:
|
266 |
+
abort(404)
|
267 |
+
predicts = u.predicts.order_by(Predict.predict_time.desc()).paginate(
|
268 |
+
page=page_num,
|
269 |
+
per_page=current_app.config['PREDICT_PER_PAGE'],
|
270 |
+
error_out=False)
|
271 |
+
|
272 |
+
# 下一页的url
|
273 |
+
next_url = url_for('predict_history', page=predicts.next_num, username=current_user.username) if predicts.has_next else None
|
274 |
+
prev_url = url_for('predict_history', page=predicts.prev_num, username=current_user.username) if predicts.has_prev else None
|
275 |
+
|
276 |
+
return render_template(
|
277 |
+
'predict_history.html',
|
278 |
+
title='History',
|
279 |
+
allpredicts=predicts.items,
|
280 |
+
user=u,
|
281 |
+
next_url=next_url,
|
282 |
+
prev_url=prev_url,
|
283 |
+
totol_num=u.predicts.count() - (page_num-1)*current_app.config['PREDICT_PER_PAGE'],
|
284 |
+
en2ch=utils.en2ch
|
285 |
+
)
|
286 |
+
|
287 |
+
@login_required
|
288 |
+
def feedback_history():
|
289 |
+
u = User.query.filter_by(username=current_user.username).first()
|
290 |
+
|
291 |
+
# 默认第一页
|
292 |
+
page_num = request.args.get('page') or "1"
|
293 |
+
if page_num.isdigit():
|
294 |
+
page_num = int(page_num)
|
295 |
+
else:
|
296 |
+
abort(404)
|
297 |
+
feedbacks = u.tweets.order_by(Tweet.create_time.desc()).paginate(
|
298 |
+
page=page_num,
|
299 |
+
per_page=current_app.config['TWEET_PER_PAGE'],
|
300 |
+
error_out=False)
|
301 |
+
allfeedbacks = []
|
302 |
+
for per in feedbacks.items:
|
303 |
+
allfeedbacks.append("usr_predict_images/{}/{}.jpg".format(current_user.username, per.img))
|
304 |
+
# 下一页的url
|
305 |
+
next_url = url_for('feedback_history', page=feedbacks.next_num, username=current_user.username) if feedbacks.has_next else None
|
306 |
+
prev_url = url_for('feedback_history', page=feedbacks.prev_num, username=current_user.username) if feedbacks.has_prev else None
|
307 |
+
|
308 |
+
return render_template(
|
309 |
+
'feedback_history.html',
|
310 |
+
title='History',
|
311 |
+
allfeedbacks=feedbacks.items,
|
312 |
+
user=u,
|
313 |
+
next_url=next_url,
|
314 |
+
prev_url=prev_url,
|
315 |
+
totol_num=u.tweets.count() - (page_num - 1) * current_app.config['TWEET_PER_PAGE']
|
316 |
+
)
|
317 |
+
|
318 |
+
@login_required
|
319 |
+
def feedback():
|
320 |
+
form = TweetForm()
|
321 |
+
# 发文
|
322 |
+
if form.validate_on_submit():
|
323 |
+
t = Tweet(body=form.tweet.data, author=current_user, img=request.form['imgname'])
|
324 |
+
db.session.add(t)
|
325 |
+
db.session.commit()
|
326 |
+
return redirect(url_for('index'))
|
327 |
+
u = User.query.filter_by(username=current_user.username).first()
|
328 |
+
|
329 |
+
value = str(request.args.get('value') or None)
|
330 |
+
|
331 |
+
designated = False
|
332 |
+
if value == "None": # 没指定,则返回最新的图片
|
333 |
+
# predict图片
|
334 |
+
predict_img = u.predicts.order_by(Predict.predict_time.desc()).paginate(
|
335 |
+
page=1,
|
336 |
+
per_page=current_app.config['TWEET_PER_PAGE'],
|
337 |
+
error_out=False)
|
338 |
+
predict_img = predict_img.items[0]
|
339 |
+
value = predict_img.img_name
|
340 |
+
else: # value不为空表示指定了哪张图片
|
341 |
+
predict_img = u.predicts.filter_by(img_name=value).first()
|
342 |
+
designated = True
|
343 |
+
|
344 |
+
find_ = u.tweets.filter_by(img=value).first()
|
345 |
+
feedbacked = False
|
346 |
+
if find_ is not None:
|
347 |
+
feedbacked = True
|
348 |
+
img_path = predict_img.img_path
|
349 |
+
predict_img.img_path = "".join([img_path[:-33], '/', img_path[-32:]])
|
350 |
+
return render_template('feedback.html',
|
351 |
+
form=form,
|
352 |
+
find_=find_,
|
353 |
+
feedbacked=feedbacked,
|
354 |
+
designated=designated,
|
355 |
+
predict_img=predict_img,
|
356 |
+
en2ch=utils.en2ch)
|
357 |
+
|
358 |
+
@login_required
|
359 |
+
def predict():
|
360 |
+
if request.method == 'GET':
|
361 |
+
return render_template('predict.html')
|
362 |
+
if request.method == 'POST':
|
363 |
+
message = request.get_json(force=True)
|
364 |
+
encoded = message["image"]
|
365 |
+
decoded = base64.b64decode(encoded)
|
366 |
+
img = Image.open(io.BytesIO(decoded))
|
367 |
+
print(img.mode)
|
368 |
+
now = datetime.datetime.now()
|
369 |
+
|
370 |
+
destination = "static/usr_predict_images/{}".format(current_user.username)
|
371 |
+
if not os.path.exists(destination):
|
372 |
+
os.makedirs(destination)
|
373 |
+
|
374 |
+
randomPost = False
|
375 |
+
rand_str = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
|
376 |
+
if randomPost:
|
377 |
+
ra1, ra2, ra3, ra4 = random.randint(15, 21), random.randint(1, 9), random.randint(1, 9), random.randint(1, 9)
|
378 |
+
randomtime_file = '20{}-0{}-1{}-1{}-33-48-'.format(ra1, ra2, ra3, ra4)
|
379 |
+
randomtime_db = datetime.datetime.strptime('20{}-0{}-1{} 1{}:33:48'.format(ra1, ra2, ra3, ra4), "%Y-%m-%d %H:%M:%S")
|
380 |
+
file_name = os.path.join(destination, randomtime_file + rand_str + '.jpg')
|
381 |
+
else:
|
382 |
+
file_name = os.path.join(destination, str(now.strftime("%Y-%m-%d-%H-%M-%S-")) + rand_str + '.jpg')
|
383 |
+
|
384 |
+
|
385 |
+
try:
|
386 |
+
if img.mode != "RGB": # jpeg是RGB
|
387 |
+
img = img.convert('RGB')
|
388 |
+
img.save(os.path.join(file_name), "JPEG", quality=80, optimize=True, progressive=True)
|
389 |
+
except IOError:
|
390 |
+
ImageFile.MAXBLOCK = img.size[0] * img.size[1]
|
391 |
+
img.save(file_name, "JPEG", quality=80, optimize=True, progressive=True)
|
392 |
+
|
393 |
+
t = label_image.read_tensor_from_image_file(file_name,
|
394 |
+
input_height=input_height,
|
395 |
+
input_width=input_width,
|
396 |
+
input_mean=input_mean,
|
397 |
+
input_std=input_std)
|
398 |
+
|
399 |
+
input_name = "import/" + input_layer
|
400 |
+
output_name = "import/" + output_layer
|
401 |
+
input_operation = graph.get_operation_by_name(input_name);
|
402 |
+
output_operation = graph.get_operation_by_name(output_name);
|
403 |
+
|
404 |
+
with tf.Session(graph=graph) as sess:
|
405 |
+
start = time.time()
|
406 |
+
results = sess.run(output_operation.outputs[0],
|
407 |
+
{input_operation.outputs[0]: t})
|
408 |
+
end = time.time()
|
409 |
+
|
410 |
+
results = np.squeeze(results)
|
411 |
+
|
412 |
+
top_k = results.argsort()[-5:][::-1]
|
413 |
+
labels = label_image.load_labels(label_file)
|
414 |
+
|
415 |
+
print('\nEvaluation time (1-image): {:.3f}s\n'.format(end - start))
|
416 |
+
|
417 |
+
# top_k [35 18 29 28 30]
|
418 |
+
for i in top_k:
|
419 |
+
if max(results) == results[i]:
|
420 |
+
res = results[i]
|
421 |
+
lab = labels[i]
|
422 |
+
print(labels[i], results[i], "this is max")
|
423 |
+
else:
|
424 |
+
print(labels[i], results[i], "this is not max")
|
425 |
+
# 入库
|
426 |
+
if randomPost:
|
427 |
+
t = Predict(img_name=file_name[-32:-4], img_path=file_name, size=str(img.size[0]) + "*" + str(img.size[1]),
|
428 |
+
predict_time=randomtime_db, predict_result=lab, predict_value=str(res), author=current_user)
|
429 |
+
else:
|
430 |
+
t = Predict(img_name=file_name[-32:-4], img_path=file_name, size=str(img.size[0]) + "*" + str(img.size[1]),
|
431 |
+
predict_result=lab, predict_value=str(res), author=current_user)
|
432 |
+
ch = utils.en2ch[lab]
|
433 |
+
db.session.add(t)
|
434 |
+
db.session.commit()
|
435 |
+
response = {
|
436 |
+
'prediction': {
|
437 |
+
'species': ch.split(' ')[0],
|
438 |
+
'condition': ' '.join(ch.split(' ')[1:]),
|
439 |
+
'value': str(res)
|
440 |
+
}
|
441 |
+
}
|
442 |
+
return jsonify(response)
|
443 |
+
|
444 |
+
@login_required
|
445 |
+
def predictbykind():
|
446 |
+
if request.method == 'POST':
|
447 |
+
value = request.get_json(force=True)["value"]
|
448 |
+
encoded = request.get_json(force=True)["image"]
|
449 |
+
decoded = base64.b64decode(encoded)
|
450 |
+
image = Image.open(io.BytesIO(decoded))
|
451 |
+
|
452 |
+
# 保存图片
|
453 |
+
now = datetime.datetime.now()
|
454 |
+
destination = "static/usr_predict_images/{}".format(current_user.username)
|
455 |
+
if not os.path.exists(destination):
|
456 |
+
os.makedirs(destination)
|
457 |
+
rand_str = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
|
458 |
+
file_name = os.path.join(destination, str(now.strftime("%Y-%m-%d-%H-%M-%S-")) + rand_str + '.jpg')
|
459 |
+
try:
|
460 |
+
if image.mode != "RGB": # jpeg是RGB
|
461 |
+
image = image.convert('RGB')
|
462 |
+
image.save(os.path.join(file_name), "JPEG", quality=80, optimize=True, progressive=True)
|
463 |
+
except IOError:
|
464 |
+
ImageFile.MAXBLOCK = image.size[0] * image.size[1]
|
465 |
+
image.save(file_name, "JPEG", quality=80, optimize=True, progressive=True)
|
466 |
+
|
467 |
+
response = utils.infer_special(value, image)
|
468 |
+
|
469 |
+
# 入库
|
470 |
+
t = Predict(img_name=file_name[-32:-4], img_path=file_name, size=str(image.size[0]) + "*" + str(image.size[1]),
|
471 |
+
predict_result=" ".join([value, response['conditionen']]),
|
472 |
+
predict_value=response['prediction']['value'], author=current_user)
|
473 |
+
db.session.add(t)
|
474 |
+
db.session.commit()
|
475 |
+
return jsonify(response)
|
476 |
+
|
477 |
+
@login_required
|
478 |
+
def dashboard():
|
479 |
+
time_now = datetime.datetime.now()
|
480 |
+
|
481 |
+
# join实现复杂查询https://www.kancloud.cn/tokimeki/flask_notebook/775173
|
482 |
+
# 方法一,查看有病的
|
483 |
+
same_city_count = 0
|
484 |
+
for u, a in db.session.query(User, Predict).filter(User.id == Predict.user_id).all():
|
485 |
+
if u.city == current_user.city and 'healthy' not in a.predict_result:
|
486 |
+
same_city_count+=1
|
487 |
+
|
488 |
+
# 方法二,查看有病的,只要包含healthy的label就不算有病
|
489 |
+
all_of_same_city = Predict.query.join(User, (User.id == Predict.user_id)).filter_by(city=current_user.city).filter(and_(Predict.predict_result.notlike('%healthy%'), Predict.predict_result.notlike('%healthy')))
|
490 |
+
|
491 |
+
# 以后按这样来,以免算法有问题,如果两个都一致,结果就没问题
|
492 |
+
assert same_city_count == all_of_same_city.count()
|
493 |
+
|
494 |
+
timeline = request.args.get('timeline') or "week"
|
495 |
+
type_ = request.args.get('type') or "allkinds"
|
496 |
+
|
497 |
+
return utils.getStatistics(timeline, type_, all_of_same_city, time_now, current_user)
|
498 |
+
|
499 |
+
|
500 |
+
def predict_for_visitor():
|
501 |
+
if request.method == 'GET':
|
502 |
+
try:
|
503 |
+
username = request.args.get('username')
|
504 |
+
except:
|
505 |
+
print("重造")
|
506 |
+
username = "visitor" + ''.join(random.choice(string.digits) for _ in range(8))
|
507 |
+
ip = request.remote_addr
|
508 |
+
addr = utils.getAddrFromIP(ip)
|
509 |
+
user = User(
|
510 |
+
username=username,
|
511 |
+
email=utils.RandomEmail(),
|
512 |
+
country=addr["ct"],
|
513 |
+
city=addr["city"],
|
514 |
+
province=addr["prov"]
|
515 |
+
)
|
516 |
+
user.is_visitor = True
|
517 |
+
return render_template('predict.html', current_user=user)
|
518 |
+
if request.method == 'POST':
|
519 |
+
value = request.get_json(force=True)["value"]
|
520 |
+
encoded = request.get_json(force=True)["image"]
|
521 |
+
decoded = base64.b64decode(encoded)
|
522 |
+
image = Image.open(io.BytesIO(decoded))
|
523 |
+
if image.mode != "RGB": # jpeg是RGB
|
524 |
+
image = image.convert('RGB')
|
525 |
+
response = utils.infer_special(value, image)
|
526 |
+
return jsonify(response)
|
527 |
+
|
528 |
+
|
529 |
+
def intro():
|
530 |
+
value = str(request.args.get('value') or "apple")
|
531 |
+
if value in utils.classname:
|
532 |
+
return render_template("intros/intro_{}.html".format(value))
|
533 |
+
abort(404)
|
534 |
+
|
535 |
+
|
536 |
+
def article():
|
537 |
+
value = request.args.get('value') or "1"
|
538 |
+
if value.isdigit():
|
539 |
+
value = int(value)
|
540 |
+
else:
|
541 |
+
abort(404)
|
542 |
+
if value == 1:
|
543 |
+
return render_template("articles/article{}.html".format(value))
|
544 |
+
if value == 2:
|
545 |
+
return render_template("articles/article{}.html".format(value))
|
546 |
+
abort(404)
|
detectweb/templates/404.html
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
|
5 |
+
<h1>Sorry, that page doesn’t exist!</h1>
|
6 |
+
|
7 |
+
{% endblock %}
|
detectweb/templates/_tweets.html
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<table class="table table-hover">
|
2 |
+
|
3 |
+
</table>
|
4 |
+
<div class="my-3 p-3 bg-body rounded shadow-sm">
|
5 |
+
<h6 class="border-bottom pb-2 mb-0">最近</h6>
|
6 |
+
{% for tweet in tweets %}
|
7 |
+
<div class="d-flex text-muted pt-3">
|
8 |
+
<img src="{{ tweet.author.avatar(48) }}" class="rounded-circle" alt="">
|
9 |
+
<p class="pb-3 mb-0 small lh-sm border-bottom">
|
10 |
+
<a href="{{ url_for('profile', username=tweet.author.username) }}">
|
11 |
+
<strong class="fw-bold text-dark">{{ tweet.author.username }}</strong>
|
12 |
+
</a>
|
13 |
+
{{ tweet.create_time }}<br>
|
14 |
+
{{ tweet.body }}
|
15 |
+
</p>
|
16 |
+
</div>
|
17 |
+
{% endfor %}
|
18 |
+
</div>
|
detectweb/templates/articles/article1.html
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!doctype html>
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="utf-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7 |
+
<title>如何推进农业产业绿色振兴</title>
|
8 |
+
|
9 |
+
|
10 |
+
<!-- Bootstrap core CSS -->
|
11 |
+
<link href="/static/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
12 |
+
|
13 |
+
<style>
|
14 |
+
.bd-placeholder-img {
|
15 |
+
font-size: 1.125rem;
|
16 |
+
text-anchor: middle;
|
17 |
+
-webkit-user-select: none;
|
18 |
+
-moz-user-select: none;
|
19 |
+
user-select: none;
|
20 |
+
}
|
21 |
+
|
22 |
+
@media (min-width: 768px) {
|
23 |
+
.bd-placeholder-img-lg {
|
24 |
+
font-size: 3.5rem;
|
25 |
+
}
|
26 |
+
}
|
27 |
+
</style>
|
28 |
+
|
29 |
+
<!-- Custom styles for this template -->
|
30 |
+
<link href="https://fonts.googleapis.com/css?family=Playfair+Display:700,900&display=swap" rel="stylesheet">
|
31 |
+
</head>
|
32 |
+
<body>
|
33 |
+
|
34 |
+
<main class="container">
|
35 |
+
<div class="col-md-12">
|
36 |
+
<h3 class="pb-4 mb-4 fst-italic border-bottom">
|
37 |
+
科普系列
|
38 |
+
</h3>
|
39 |
+
|
40 |
+
<article class="blog-post">
|
41 |
+
<h2 class="blog-post-title">如何推进农业产业绿色振兴</h2>
|
42 |
+
<p class="blog-post-meta">October, 2019 by <a href="http://news.sciencenet.cn/sbhtmlnews/2019/10/350004.shtm">翁伯琦</a></p>
|
43 |
+
|
44 |
+
<p>如何充分发挥科技兴农作用、怎样有效促进产业绿色振兴,无疑是新时代赋予农业科研院所与科技人员的新命题。就总体发展思路而言,要以科技创新为基础,助力乡村科技创业;以科技兴农为支撑,促进产业绿色振兴;有效保障粮食安全、食品安全、生态安全;着力提高土地产出率、劳动生产率、资源利用率、污染防控率;完善并提升作业机械化、生产标准化、管理智能化、开发高优化、产业绿色化、产品品牌化、功能多样化、三产融合化、增收持续化;实现农业强、农民富、农村美的主体目标。</p>
|
45 |
+
<hr>
|
46 |
+
<p>以科技兴农推动质量强农与绿色强农,要着力构建高优生产体系、高效产业体系、高值经营体系。事实上,强化科技兴农作用,需要注重把握5个重要环节:优良品种选育、高优技术配套、先进设施应用、产品加工提质、多样功能开发。强化产业绿色振兴,同样需要把握5个关键环节:维护良好生态、严格防控污染、土壤质量保育、农牧有机结合、废物循环利用。</p>
|
47 |
+
|
48 |
+
<h2>五大方面</h2>
|
49 |
+
<p>不言而喻,乡村科技兴农与产业绿色振兴是息息相关的,其相互交融、相互促进、相互支持、相互契合,进而保障资源节约、产出提高、环境友好、增收致富的目标实现。就发展对策而言,要着力把握5个方面:</p>
|
50 |
+
<h3>优化农业绿色发展格局</h3>
|
51 |
+
<p>如何落实国家粮食安全与保障供应的重大部署,首先要注重“农业三区”建设,即粮食生产功能区、重要农产品生产保护区、特色及优质农产品生产区建设与完善。粮食生产功能区,即要从保障粮食安全的战略高度审视种植产业发展,划定9亿亩的小麦与玉米生产区,着力并有效保障口粮供应,牢牢端好中国人自己的饭碗。重要农产品生产保护区,即针对大豆、棉花、油菜、天然橡胶等产品特性划定生产区域,满足人们生活与经济发展需求。特色与优质农产品生产区,即要发挥各个地域、各生态区优势,因地制宜与因势利导创造特色农业竞争优势。</p>
|
52 |
+
|
53 |
+
<h3>“示范园区”建设</h3>
|
54 |
+
<p>即分门别类构建现代农业科技示范园区、农业可持续发展示范区、现代绿色农业产业园区的建设体系,并以此作为推动“农业三区”建设的样板基地与重要抓手,全面形成农业绿色发展的新格局,着力提高农产品的市场竞争实力,以实现现代农业的高产、优质、高效、安全、生态的发展目标。</p>
|
55 |
+
|
56 |
+
<h3>全面实施基础保障建设</h3>
|
57 |
+
<p>
|
58 |
+
为了保护和提升农业产能,同时保障绿色与高优生产,需要把握5个基础环节:建设标准农田,配套水利设施与土壤质量保育措施;建设技术体系,优化耕作制度与资源高效利用措施;建设种苗体系,引进选育并重且集成推广优良品种;建设管理体系,实施绿色管控标准化与智能化运营;强化风险防控,加强病虫害管理及其防灾减灾措施。
|
59 |
+
</p>
|
60 |
+
|
61 |
+
<h3>农业绿色振兴</h3>
|
62 |
+
<p>
|
63 |
+
就农业绿色振兴而言,无疑需要提升科技创新与科技创业的保障能力。就此,要充分挖掘动植物的遗传潜力,着力深化新品种的选育;要充分提高农业资源利用效率,推动农机农艺有效结合;要充分发挥乡村洁净场地作用,集成推广清洁生产技术;要充分发挥绿色标准化的作用,完善溯源及其监测技术;要充分应用农业环境基准方法,合理构建核算评估体系。
|
64 |
+
</p>
|
65 |
+
|
66 |
+
<h3>探索生态循环农业模式</h3>
|
67 |
+
<p>
|
68 |
+
目前每年种植业秸秆产生量7亿吨,养殖业废弃物产生量38亿吨,如果不进行有效循环利用,将成为巨大污染源,如果将其有效循环利用,就能够获得潜力巨大的农业生产资源。要尽快把农业发展从单一的追求经济效益转到经济和生态兼顾的目标上来,着力探索并构建特色各具的生态循环农业发展模式。
|
69 |
+
</p>
|
70 |
+
其重点包括4个方面:
|
71 |
+
<ul>
|
72 |
+
<li>优化种植制度,例如玉米、大豆轮作制,既有利于生产,又有利于地力培育;</li>
|
73 |
+
<li>优化农牧结合,在畜牧业养殖区,要实施种植业有效吸纳与优化匹配,既保障种植业生产,又有利于养分转化利用;</li>
|
74 |
+
<li>优化农菌耦合,以种植业作物秸秆+养殖业废弃物质优化组合,有效发展高效食用菌产业,生产菌物蛋白,丰富食品供应;</li>
|
75 |
+
<li>优化农草融合,在果园与茶园实施生草栽培,既可以防控水土流失,保护生态环境,又能够开发农区草业,增加农民收入,进而构建资源节约与环境友好的绿色农业发展新模式,创立新机制,取得新成效。</li>
|
76 |
+
</ul>
|
77 |
+
|
78 |
+
<h3>推行优质产品绿色生产。</h3>
|
79 |
+
<p>注重应用先进信息技术,优化构建与完善农业生产标准化体系,重点是实施绿色生产过程防控技术,推动绿色标准农业产品生产;关键是实行优质农产品的绿色生产措施,着力抓好“一控两减三基本”技术体系构建与完善工作。强化水利设施建设,保障水资源利用效率提高,水的平均利用效率要从0.52提高至0.55以上;严格实施“两减”技术措施,减少化学肥料与化学农药使用量30%,研究并替代30%以上高效有机肥料与生物农药,并对农产品质量进行提标增效。同时要完善产业化标准,实现优质优价的统一,从源头上保障优质农产品的绿色生产。还要大力发展节水、节地、节药、节能以及减少温室气体排放的技术,大力推进绿色生产模式创新与“三生”技术集成融合,使农业科技创新速度超越绿色农业发展步伐,有效服务绿色振兴,全面助力农民增收。</p>
|
80 |
+
|
81 |
+
<p>拓展绿色农业多样功能。在巩固优质高效生产成果的同时,应进一步深入探索更多点绿成金的生产和加工配套技术。农业还拥有生态、生活、文化、旅游、观光等多样功能,需要进一步深入探讨与充分挖掘潜力。实际上,良好的生态价值是难以用金钱衡量的,其不仅体现在农产品上,更蕴含在生存质量中。随着健康中国规划的实施,在生态环境优良的地区发展旅游观光,促进三产融合;发展休闲养生,促进康复健体。这都有助于点绿成金目标的实现。为此,需要进行农业生态功能的评估和价值核算,探索和完善生态服务产业体系,包括制定标准,树立品牌;做大规模、配套设施;科学评估,有效监管,以科技创新支撑绿色农业多功能发展。</p>
|
82 |
+
|
83 |
+
</article><!-- /.blog-post -->
|
84 |
+
|
85 |
+
</div>
|
86 |
+
</main>
|
87 |
+
|
88 |
+
<footer class="text-muted py-5">
|
89 |
+
<div class="container">
|
90 |
+
<p class="float-end mb-1">
|
91 |
+
<a href="#">Back to top</a>
|
92 |
+
</p>
|
93 |
+
<p class="mb-1">Reference: http://news.sciencenet.cn/sbhtmlnews/2019/10/350004.shtm</p>
|
94 |
+
</div>
|
95 |
+
</footer>
|
96 |
+
</body>
|
97 |
+
</html>
|
detectweb/templates/articles/article2.html
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!doctype html>
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="utf-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7 |
+
|
8 |
+
<title>如何进行科学施肥</title>
|
9 |
+
|
10 |
+
<link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/blog/">
|
11 |
+
|
12 |
+
<!-- Bootstrap core CSS -->
|
13 |
+
<link href="/static/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
14 |
+
|
15 |
+
<style>
|
16 |
+
.bd-placeholder-img {
|
17 |
+
font-size: 1.125rem;
|
18 |
+
text-anchor: middle;
|
19 |
+
-webkit-user-select: none;
|
20 |
+
-moz-user-select: none;
|
21 |
+
user-select: none;
|
22 |
+
}
|
23 |
+
|
24 |
+
@media (min-width: 768px) {
|
25 |
+
.bd-placeholder-img-lg {
|
26 |
+
font-size: 3.5rem;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
</style>
|
30 |
+
|
31 |
+
<!-- Custom styles for this template -->
|
32 |
+
<link href="https://fonts.googleapis.com/css?family=Playfair+Display:700,900&display=swap" rel="stylesheet">
|
33 |
+
</head>
|
34 |
+
<body>
|
35 |
+
|
36 |
+
<main class="container">
|
37 |
+
<div class="col-md-12">
|
38 |
+
<h3 class="pb-4 mb-4 fst-italic border-bottom">
|
39 |
+
科普系列
|
40 |
+
</h3>
|
41 |
+
|
42 |
+
<article class="blog-post">
|
43 |
+
<h2 class="blog-post-title">如何进行科学施肥?科学施肥的方法</h2>
|
44 |
+
<p class="blog-post-meta">January 14, 2021 by <a href="https://www.my478.com/html/20210114/327577.html">农业种植网</a></p>
|
45 |
+
|
46 |
+
<p>
|
47 |
+
对农作物施肥一直是农业生产中重要的环节,施肥技术的好坏决定着农作物的生长情况,那究竟该如何进行科学的施肥呢?下面就给大家总结一下科学施肥的方法。
|
48 |
+
</p>
|
49 |
+
<hr>
|
50 |
+
|
51 |
+
<h3>按照土壤肥力施肥</h3>
|
52 |
+
<p>
|
53 |
+
按照土壤肥力施肥也就是所谓的测土配方施肥,又称平衡施肥。本着土壤缺什么补什么,缺多少,补多少的原则进行施肥。
|
54 |
+
</p>
|
55 |
+
|
56 |
+
<p>
|
57 |
+
测土配方施肥简单的说就是以土壤测试为基础,根据土壤供肥能力、作物需肥规律和肥料效应,在合理施用有机肥的基础上,提出氮、磷、钾及微量元素合理的施用数量、施肥时期和方法,以达到提高肥料利用率和作物产量、改善农产品品质的目的。
|
58 |
+
</p>
|
59 |
+
|
60 |
+
<h3>按照土壤特性施肥</h3>
|
61 |
+
<ul>
|
62 |
+
<li>南方地区的红壤、砖红壤、黄壤、黄棕壤、棕壤呈酸性或微酸性,施用磷肥宜用偏碱性的钙镁磷肥。</li>
|
63 |
+
<li>北方土壤黑钙土、栗钙土、灰钙土、褐土等多呈碱性,施用磷肥宜用偏酸性的过磷酸钙。</li>
|
64 |
+
<li>连续施肥多年的大棚、老菜田一般呈逐步酸化趋势,且钙镁元素缺乏,磷肥宜选用偏碱性的钙镁磷肥、磷矿粉等,既可调节土壤酸度,又可供应钙镁元素。</li>
|
65 |
+
<li>有盐渍化特征的碱土、盐土,尤其是滨海盐土,可以施用磷石膏,施用钾肥宜选用硫酸钾。</li>
|
66 |
+
</ul>
|
67 |
+
|
68 |
+
<h3>按照作物需肥特性施肥</h3>
|
69 |
+
<p>
|
70 |
+
施肥时,应根据不同作物的需肥特性合理施用,以提高肥料的利用率,达到作物高产优质的目的。
|
71 |
+
</p>
|
72 |
+
<ul>
|
73 |
+
<li>禾谷类作物,如小麦、玉米、水稻需氮较多,钾次之,一般田应增施氮肥或选用高氮复合肥,高产田要注重钾肥的施用。</li>
|
74 |
+
<li>豆科作物本身有根瘤,可以从空气中取氮,且对磷的需要较多,应选择低氮、高磷复合肥。</li>
|
75 |
+
<li>块茎、根茎类作物如甘薯、马铃薯需要较多的钾,应选用高钾复合肥。</li>
|
76 |
+
<li>棉、麻类等纤维作物需钠作为养分,使纤维紧密,强度提高,又是喜钾作物。</li>
|
77 |
+
<li>烟草、葡萄、苹果、茶等作物不宜使用含氯肥料。</li>
|
78 |
+
</ul>
|
79 |
+
|
80 |
+
<h3>掌握施肥的两个关键时期</h3>
|
81 |
+
<p>
|
82 |
+
作物营养临界期:一般是在幼苗期,这一时期的特点是作物需要养分并不多,但很迫切,如果缺乏养分则对以后的生长发育影响很大。
|
83 |
+
</p>
|
84 |
+
<p>
|
85 |
+
肥料效率期:一般是在作物旺盛生长时期,此时需要养分数量大,追肥效果非常好。如:玉米在大喇叭口期,小麦在拔节、孕穗期,棉花在花铃期。
|
86 |
+
</p>
|
87 |
+
|
88 |
+
<h3>掌握科学的施肥方式</h3>
|
89 |
+
<p>
|
90 |
+
一个完整的作物施肥方案是由基肥、种肥和追肥三种施肥方式组成的。基肥是在作物播种前或定植时施用的肥料,以有机肥为主,常配合施用一部分化肥。种肥是在作物播种时,施于种子附近的肥料,主要是供苗期利用的养分。追肥是在作物生长期间施用的肥料,它能及时满足作物中后期对养分的要求。追肥主要用化学氮肥。根据实际情况,三���施肥方式要灵活掌握,不要强求一致。
|
91 |
+
</p>
|
92 |
+
</article><!-- /.blog-post -->
|
93 |
+
|
94 |
+
</div>
|
95 |
+
</main>
|
96 |
+
|
97 |
+
<footer class="text-muted py-5">
|
98 |
+
<div class="container">
|
99 |
+
<p class="float-end mb-1">
|
100 |
+
<a href="#">Back to top</a>
|
101 |
+
</p>
|
102 |
+
<p class="mb-1">Reference: https://www.my478.com/html/20210114/327577.html</p>
|
103 |
+
</div>
|
104 |
+
</footer>
|
105 |
+
</body>
|
106 |
+
</html>
|
detectweb/templates/base.html
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
7 |
+
|
8 |
+
{# <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">#}
|
9 |
+
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
10 |
+
<!-- JavaScript Bundle with Popper -->
|
11 |
+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
|
12 |
+
{% if title %}
|
13 |
+
<title>{{ title }}</title>
|
14 |
+
{% else %}
|
15 |
+
<title>欢迎来到DetectWeb</title>
|
16 |
+
{% endif %}
|
17 |
+
|
18 |
+
</head>
|
19 |
+
<body style="background-color:#f3f8ff;">
|
20 |
+
|
21 |
+
<div class="sticky-top d-flex flex-column flex-md-row align-items-center p-2 px-md-4 mb-3 bg-body border-bottom shadow-sm">
|
22 |
+
{% if current_user.is_visitor %}
|
23 |
+
<a class="h5 my-0 me-md-auto text-dark fw-bold" style="text-decoration:none" data-bs-toggle="popover" data-bs-trigger="hover focus" role="button" title="访问受限" data-bs-content="注册登录开启更多功能">DetectWeb</a>
|
24 |
+
{% else %}
|
25 |
+
<a class="h5 my-0 me-md-auto text-dark fw-bold" style="text-decoration:none" href="{{ url_for('index') }}">DetectWeb</a>
|
26 |
+
{% endif %}
|
27 |
+
<nav class="my-2 my-md-0 me-md-3">
|
28 |
+
{% if current_user.is_visitor %}
|
29 |
+
<a class="p-2 text-dark" data-bs-toggle="popover" data-bs-trigger="hover focus" role="button" title="访问受限" data-bs-content="注册登录开启更多功能">发现</a>
|
30 |
+
{% else %}
|
31 |
+
<a class="p-2 text-dark" href="{{ url_for('explore') }}">发现</a>
|
32 |
+
{% endif %}
|
33 |
+
</nav>
|
34 |
+
<!-- is_anonymous表示没有登陆 -->
|
35 |
+
{% if current_user.is_anonymous %}
|
36 |
+
<a class="btn btn-outline-primary" href="{{ url_for('login') }}">登录</a>
|
37 |
+
{% else %}
|
38 |
+
<a class="btn btn-outline-primary" href="{{ url_for('logout') }}">登出</a>
|
39 |
+
{% endif %}
|
40 |
+
</div>
|
41 |
+
<script>
|
42 |
+
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
|
43 |
+
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
|
44 |
+
return new bootstrap.Popover(popoverTriggerEl)
|
45 |
+
})
|
46 |
+
</script>
|
47 |
+
{% with messages = get_flashed_messages(with_categories=True) %}
|
48 |
+
{% if messages %}
|
49 |
+
{% for message in messages %}
|
50 |
+
{% if message[0] == "message" %}
|
51 |
+
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
52 |
+
{{ message[1] }}
|
53 |
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
54 |
+
</div>
|
55 |
+
{% else %}
|
56 |
+
<div class="alert alert-{{ message[0] }} alert-dismissible fade show" role="alert">
|
57 |
+
{{ message[1] }}
|
58 |
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
59 |
+
</div>
|
60 |
+
{% endif %}
|
61 |
+
{% endfor %}
|
62 |
+
{% endif %}
|
63 |
+
{% endwith %}
|
64 |
+
<div class="container-fluid">
|
65 |
+
{% block content %} {% endblock %}
|
66 |
+
</div>
|
67 |
+
</body>
|
detectweb/templates/dashboard.html
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
<script src="/static/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
|
5 |
+
<script type="text/javascript">
|
6 |
+
var Server = {
|
7 |
+
seven_days: {{ assign_timeline["week"] }},
|
8 |
+
thirty_days: {{ assign_timeline["month"] }},
|
9 |
+
whole_year: {{ assign_timeline["year"] }},
|
10 |
+
ten_year: {{ assign_timeline["tenyear"] }}
|
11 |
+
};
|
12 |
+
</script>
|
13 |
+
<div class="container-fluid">
|
14 |
+
<div class="row">
|
15 |
+
{% include 'sidenav.html' %}
|
16 |
+
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
17 |
+
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
18 |
+
<h1 class="h2">病害检测趋势</h1>
|
19 |
+
<div class="btn-toolbar mb-2 mb-md-0">
|
20 |
+
<div class="btn-group me-2">
|
21 |
+
{# <button type="button" class="btn btn-sm btn-outline-secondary">Share</button>#}
|
22 |
+
<button type="button" id="save" class="btn btn-sm btn-outline-secondary">导出</button>
|
23 |
+
</div>
|
24 |
+
<div class="dropdown">
|
25 |
+
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
|
26 |
+
<span data-feather="calendar"></span>
|
27 |
+
{% if assign_timeline["week"] != -1 %}
|
28 |
+
本周
|
29 |
+
{% elif assign_timeline["month"] != -1 %}
|
30 |
+
本月
|
31 |
+
{% elif assign_timeline["year"] != -1 %}
|
32 |
+
本年
|
33 |
+
{% elif assign_timeline["tenyear"] != -1 %}
|
34 |
+
近十年
|
35 |
+
{% endif %}
|
36 |
+
</button>
|
37 |
+
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
|
38 |
+
{% if assign_timeline["week"] == -1 %}
|
39 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline="week", type=type_)}}">本周</a></li>
|
40 |
+
{% endif %}
|
41 |
+
{% if assign_timeline["month"] == -1 %}
|
42 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline="month", type=type_)}}">本月</a></li>
|
43 |
+
{% endif %}
|
44 |
+
{% if assign_timeline["year"] == -1 %}
|
45 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline="year", type=type_)}}">本年</a></li>
|
46 |
+
{% endif %}
|
47 |
+
{% if assign_timeline["tenyear"] == -1 %}
|
48 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline="tenyear", type=type_)}}">近十年</a></li>
|
49 |
+
{% endif %}
|
50 |
+
</ul>
|
51 |
+
</div>
|
52 |
+
<!-- 品种 -->
|
53 |
+
<div class="dropdown">
|
54 |
+
<button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
|
55 |
+
<span data-feather="calendar"></span>
|
56 |
+
{% if assign_type["allkinds"] != -1 %}
|
57 |
+
全品种
|
58 |
+
{% elif assign_type["apple"] != -1 %}
|
59 |
+
苹果
|
60 |
+
{% elif assign_type["cherry"] != -1 %}
|
61 |
+
樱桃
|
62 |
+
{% elif assign_type["corn"] != -1 %}
|
63 |
+
玉米
|
64 |
+
{% elif assign_type["grape"] != -1 %}
|
65 |
+
葡萄
|
66 |
+
{% elif assign_type["peach"] != -1 %}
|
67 |
+
桃子
|
68 |
+
{% elif assign_type["pepper"] != -1 %}
|
69 |
+
胡椒
|
70 |
+
{% elif assign_type["potato"] != -1 %}
|
71 |
+
土豆
|
72 |
+
{% elif assign_type["tomato"] != -1 %}
|
73 |
+
西红柿
|
74 |
+
{% endif %}
|
75 |
+
</button>
|
76 |
+
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
|
77 |
+
{% if assign_type["allkinds"] == -1 %}
|
78 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="allkinds")}}">全品种</a></li>
|
79 |
+
{% endif %}
|
80 |
+
{% if assign_type["apple"] == -1 %}
|
81 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="apple")}}">苹果</a></li>
|
82 |
+
{% endif %}
|
83 |
+
{% if assign_type["cherry"] == -1 %}
|
84 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="cherry")}}">樱桃</a></li>
|
85 |
+
{% endif %}
|
86 |
+
{% if assign_type["corn"] == -1 %}
|
87 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="corn")}}">玉米</a></li>
|
88 |
+
{% endif %}
|
89 |
+
{% if assign_type["grape"] == -1 %}
|
90 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="grape")}}">葡萄</a></li>
|
91 |
+
{% endif %}
|
92 |
+
{% if assign_type["peach"] == -1 %}
|
93 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="peach")}}">桃子</a></li>
|
94 |
+
{% endif %}
|
95 |
+
{% if assign_type["pepper"] == -1 %}
|
96 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="pepper")}}">胡椒</a></li>
|
97 |
+
{% endif %}
|
98 |
+
{% if assign_type["potato"] == -1 %}
|
99 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="potato")}}">土豆</a></li>
|
100 |
+
{% endif %}
|
101 |
+
{% if assign_type["tomato"] == -1 %}
|
102 |
+
<li><a class="dropdown-item" href="{{url_for('dashboard', timeline=timeline, type="tomato")}}">西红柿</a></li>
|
103 |
+
{% endif %}
|
104 |
+
</ul>
|
105 |
+
</div>
|
106 |
+
</div>
|
107 |
+
</div>
|
108 |
+
您所在城市为 {{ user.city }}
|
109 |
+
<canvas class="my-4 w-100" id="myChart" width="900" height="380"></canvas>
|
110 |
+
|
111 |
+
<h2>
|
112 |
+
{% if assign_timeline["week"] != -1 %}
|
113 |
+
每日新增
|
114 |
+
{% elif assign_timeline["month"] != -1 %}
|
115 |
+
每日新增
|
116 |
+
{% elif assign_timeline["year"] != -1 %}
|
117 |
+
每月新增
|
118 |
+
{% elif assign_timeline["tenyear"] != -1 %}
|
119 |
+
每年新增
|
120 |
+
{% endif %}
|
121 |
+
|
122 |
+
</h2>
|
123 |
+
<canvas class="my-4 w-100" id="myChart_increase" width="900" height="380"></canvas>
|
124 |
+
</main>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
+
<script type="text/javascript">
|
128 |
+
var Canvas = document.getElementById("myChart");
|
129 |
+
var Canvas_increase = document.getElementById("myChart_increase");
|
130 |
+
document.getElementById("save").onclick = function (){
|
131 |
+
downLoad(saveAsPNG(Canvas), "趋势图");
|
132 |
+
downLoad(saveAsPNG(Canvas_increase), "新增图");
|
133 |
+
}
|
134 |
+
// 保存成jpg格式的图片
|
135 |
+
function saveAsPNG(canvas) {
|
136 |
+
return canvas.toDataURL("image/png");
|
137 |
+
}
|
138 |
+
function downLoad(url, filename){
|
139 |
+
var oA = document.createElement("a");
|
140 |
+
oA.download = filename;// 设置下载的文件名,默认是'下载'
|
141 |
+
oA.href = url;
|
142 |
+
document.body.appendChild(oA);
|
143 |
+
oA.click();
|
144 |
+
oA.remove(); // 下载之后把创建的元素删除
|
145 |
+
}
|
146 |
+
</script>
|
147 |
+
<script src="/static/docs/5.0/js/feather.min.js" integrity="sha384-uO3SXW5IuS1ZpFPKugNNWqTZRRglnUJK6UAZ/gxOX80nxEkN9NcGZTftn6RzhGWE" crossorigin="anonymous"></script>
|
148 |
+
<script src="/static/docs/5.0/js/Chart.min.js" integrity="sha384-zNy6FEbO50N+Cg5wap8IKA4M/ZnLJgzc6w2NqACZaK0u0FXfOWRRJOnQtpZun8ha" crossorigin="anonymous"></script>
|
149 |
+
<script src="/static/docs/5.0/examples/dashboard/dashboard.js"></script>
|
150 |
+
{% endblock %}
|
detectweb/templates/edit_profile.html
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
<div class='row'>
|
5 |
+
<div class="text-center col-lg-4"></div>
|
6 |
+
<div class="text-center col-lg-4">
|
7 |
+
<h1>Edit Profile</h1>
|
8 |
+
<form action="" method="post">
|
9 |
+
{{ form.hidden_tag() }}
|
10 |
+
<p>
|
11 |
+
{{ form.about_me.label }}<br>
|
12 |
+
{{ form.about_me(cols=50, rows=4) }}<br>
|
13 |
+
{% for error in form.about_me.errors %}
|
14 |
+
<span style="color: red;">[{{ error }}]</span>
|
15 |
+
{% endfor %}
|
16 |
+
</p>
|
17 |
+
<button class="btn btn-info" type="submit">Save</button>
|
18 |
+
</form>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
{% endblock %}
|
detectweb/templates/email/passwd_reset.html
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<p>我们听说你把 DetectWeb 密码弄丢了。很抱歉!</p>
|
2 |
+
|
3 |
+
<p>但别担心!您可以使用以下链接重置您的密码:</p>
|
4 |
+
|
5 |
+
<a href="{{ url_password_reset }}">{{ url_password_reset }}</a>
|
6 |
+
|
7 |
+
<p>如果你在2小时内不使用这个链接,它将过期。 要获得一个新的密码重置链接,请访问 {{ url_password_reset_request }}</p><br>
|
8 |
+
|
9 |
+
谢谢,
|
10 |
+
<br>
|
11 |
+
你在 DetectWeb 的朋友
|
detectweb/templates/email/passwd_reset.txt
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
我们听说你把 DetectWeb 密码弄丢了。很抱歉!
|
2 |
+
|
3 |
+
但别担心!您可以使用以下链接重置您的密码:
|
4 |
+
|
5 |
+
{{ url_password_reset }}
|
6 |
+
|
7 |
+
如果你在2小时内不使用这个链接,它将过期。 要获得一个新的密码重置链接,请访问 {{ url_password_reset_request }}
|
8 |
+
|
9 |
+
谢谢,
|
10 |
+
你在 DetectWeb 的朋友
|
detectweb/templates/email/user_activate.html
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
亲爱的 {{ username }},
|
2 |
+
|
3 |
+
要确认您的电子邮件地址并完成您的DetectWeb帐户的设置,请单击下面的链接。
|
4 |
+
|
5 |
+
{{ url_user_activate }}
|
detectweb/templates/email/user_activate.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
亲爱的 {{ username }},
|
2 |
+
|
3 |
+
要确认您的电子邮件地址并完成您的DetectWeb帐户的设置,请单击下面的链接。
|
4 |
+
|
5 |
+
{{ url_user_activate }}
|
detectweb/templates/explore.html
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
|
5 |
+
{% include '_tweets.html' %}
|
6 |
+
|
7 |
+
{% if prev_url %}
|
8 |
+
<a href="{{ prev_url }}">上一页</a>
|
9 |
+
{% endif %}
|
10 |
+
{% if next_url %}
|
11 |
+
<a href="{{ next_url }}">下一页</a>
|
12 |
+
{% endif %}
|
13 |
+
|
14 |
+
{% endblock %}
|
detectweb/templates/feedback.html
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
<div class="container container-table">
|
5 |
+
<div class="row vertical-center-row">
|
6 |
+
<div class="text-center col-md-12">
|
7 |
+
<img id="most-recent-image" height="350" width="350" src="{{ url_for('static', filename=predict_img.img_path[7:])}}"/>
|
8 |
+
<br>{% if designated %}指定预测:{% else %}最新预测:{% endif %}{{ predict_img.img_path[-32:-4] }}
|
9 |
+
<br>预测结果:{{ en2ch[predict_img.predict_result] }}
|
10 |
+
<br>置信度:{{ predict_img.predict_value }}
|
11 |
+
{% if feedbacked %}
|
12 |
+
<p class="text-success">上次反馈: 【{{ find_.body }}】</p>
|
13 |
+
{% endif %}
|
14 |
+
</div>
|
15 |
+
<div class="text-center col-md-12">
|
16 |
+
<form class="col-lg-6" action="" method="post" style="margin: 0 auto;">
|
17 |
+
{{ form.hidden_tag() }}
|
18 |
+
<p>
|
19 |
+
{{ form.tweet(cols=50, rows=4) }}<br>
|
20 |
+
{% for error in form.tweet.errors %}
|
21 |
+
<span style="color: red;">[{{ error }}]</span>
|
22 |
+
{% endfor %}
|
23 |
+
</p>
|
24 |
+
<input type="hidden" name="imgname" value="{{ predict_img.img_path[-32:-4] }}">
|
25 |
+
{% if feedbacked %}
|
26 |
+
<button class="btn btn-info disabled" id="feedback-button" type="submit" aria-disabled="true">已反馈</button>
|
27 |
+
{% else %}
|
28 |
+
<button class="btn btn-info" id="feedback-button" type="submit">反馈</button>
|
29 |
+
{% endif %}
|
30 |
+
</form>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
|
35 |
+
{# <!-- Latest compiled and minified CSS -->#}
|
36 |
+
{# <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">#}
|
37 |
+
{##}
|
38 |
+
<!-- jQuery library -->
|
39 |
+
<script src="/static/js/ajax/jquery.min.js"></script>
|
40 |
+
|
41 |
+
{# <!-- Latest compiled JavaScript -->#}
|
42 |
+
{# <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>#}
|
43 |
+
|
44 |
+
<script>
|
45 |
+
$("#feedback-button").click(function(){
|
46 |
+
let message = {
|
47 |
+
image: base64Image
|
48 |
+
}
|
49 |
+
console.log(message);
|
50 |
+
$.post("{{ url_for('feedback') }}", JSON.stringify(message), function(response){
|
51 |
+
$("#prediction").text(response.prediction.prediction);
|
52 |
+
$("#value").text(response.prediction.value);
|
53 |
+
console.log(response);
|
54 |
+
});
|
55 |
+
});
|
56 |
+
</script>
|
57 |
+
{% endblock %}
|
detectweb/templates/feedback_history.html
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
<link rel="stylesheet" href="/static/css/viewer.css">
|
5 |
+
<script src="/static/js/viewer.js"></script>
|
6 |
+
<script type="text/javascript">
|
7 |
+
var x = {{ totol_num }}
|
8 |
+
</script>
|
9 |
+
<div class="container-fluid">
|
10 |
+
<div class="row">
|
11 |
+
{% include 'sidenav.html' %}
|
12 |
+
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
13 |
+
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
14 |
+
<h1 class="h2">反馈记录</h1>
|
15 |
+
</div>
|
16 |
+
<div class="table-responsive">
|
17 |
+
<table class="table table-striped table-dark table-hover" style="text-align: center;vertical-align: middle;">
|
18 |
+
<thead>
|
19 |
+
<tr>
|
20 |
+
<th>#</th>
|
21 |
+
<th>图片缩略</th>
|
22 |
+
<th>图片详情</th>
|
23 |
+
<th>反馈评价</th>
|
24 |
+
<th>图片操作</th>
|
25 |
+
</tr>
|
26 |
+
</thead>
|
27 |
+
<tbody>
|
28 |
+
{% for per in allfeedbacks %}
|
29 |
+
<tr>
|
30 |
+
<td><script>document.write(x);x -= 1</script></td>
|
31 |
+
<td><img id="{{ per.img }}" src="{{ url_for('static', filename="usr_predict_images/{}/{}.jpg".format(current_user.username, per.img)) }}" width="120" height="120"></td>
|
32 |
+
<td>{{ per.img }}</td>
|
33 |
+
<td>{{ per.body }}</td>
|
34 |
+
<td>
|
35 |
+
<a href="#" class="text-white" onclick="showImg('{{ per.img }}')">查看大图</a>
|
36 |
+
</td>
|
37 |
+
</tr>
|
38 |
+
{% endfor %}
|
39 |
+
<div class="d-grid gap-2 d-md-flex justify-content-md-between mb-1">
|
40 |
+
{% if prev_url %}
|
41 |
+
<a href="{{ prev_url }}" class="btn btn-outline-primary btn-sm">上一页</a>
|
42 |
+
{% else %}
|
43 |
+
<a href="#" class="btn btn-outline-primary btn-sm disabled" aria-disabled="true">上一页</a>
|
44 |
+
{% endif %}
|
45 |
+
{% if next_url %}
|
46 |
+
<a href="{{ next_url }}" class="btn btn-outline-primary btn-sm">下一页</a>
|
47 |
+
{% else %}
|
48 |
+
<a href="#" class="btn btn-outline-primary btn-sm disabled" aria-disabled="true">下一页</a>
|
49 |
+
{% endif %}
|
50 |
+
</div>
|
51 |
+
</tbody>
|
52 |
+
</table>
|
53 |
+
</div>
|
54 |
+
|
55 |
+
</main>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
<script type="text/javascript">
|
59 |
+
function showImg(id){
|
60 |
+
var image = new Viewer(document.getElementById(id),{
|
61 |
+
url: 'data-original'
|
62 |
+
});
|
63 |
+
document.getElementById(id).click();
|
64 |
+
}
|
65 |
+
</script>
|
66 |
+
|
67 |
+
{% endblock %}
|
detectweb/templates/index.html
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{% extends "base.html" %}
|
2 |
+
|
3 |
+
{% block content %}
|
4 |
+
{% if current_user.is_visitor %}
|
5 |
+
{% include 'limits.html' %}
|
6 |
+
{% endif %}
|
7 |
+
<link href="/static/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
8 |
+
<div class="container-fluid">
|
9 |
+
<div class="row">
|
10 |
+
{% include 'sidenav.html' %}
|
11 |
+
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
12 |
+
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
13 |
+
<h1 class="h2">个人中心</h1>
|
14 |
+
<h5 class="col-4 d-flex justify-content-end align-items-center">
|
15 |
+
欢迎,
|
16 |
+
{% if current_user.is_visitor %}
|
17 |
+
<a data-bs-toggle="popover" data-bs-trigger="hover focus" role="button" title="访问受限" data-bs-content="注册登录开启更多功能">
|
18 |
+
<b class="fw-bold text-dark">{{ current_user.username }}</b>
|
19 |
+
</a>
|
20 |
+
{% else %}
|
21 |
+
<a href="/{{ current_user.username }}">
|
22 |
+
<b class="fw-bold text-dark">{{ current_user.username }}</b>
|
23 |
+
</a>
|
24 |
+
{% endif %}
|
25 |
+
</h5>
|
26 |
+
</div>
|
27 |
+
<div class="nav-scroller py-1 mb-2">
|
28 |
+
<nav class="nav d-flex justify-content-between">
|
29 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="cherry") }}">樱桃篇</a>
|
30 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="tomato") }}">番茄篇</a>
|
31 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="pepper") }}">胡椒篇</a>
|
32 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="potato") }}">土豆篇</a>
|
33 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="peach") }}">桃子篇</a>
|
34 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="corn") }}">玉米篇</a>
|
35 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="grape") }}">葡萄篇</a>
|
36 |
+
<a class="p-2 link-secondary" href="{{ url_for("intro", value="apple") }}">苹果篇</a>
|
37 |
+
<a class="p-2 link-secondary" href="https://baijiahao.baidu.com/s?id=1662865033792131981&wfr=spider&for=pc" target="_blank">防治条例</a>
|
38 |
+
</nav>
|
39 |
+
</div>
|
40 |
+
<div class="p-4 p-md-5 mb-4 text-white rounded bg-dark" style="background: url('/static/images/fengshou.jfif') no-repeat center;background-size: cover">
|
41 |
+
<div class="col-md-6 px-0">
|
42 |
+
<h1 class="display-4 fst-italic">远离病虫害<br>水稻大丰收</h1>
|
43 |
+
<p class="lead my-3">2020年全国粮食生产再获丰收,总产量为13390亿斤,从病虫害防治角度,农民2021年需要注意哪些?
|
44 |
+
连日来,我国坚持“预防为主、防治结合、综合防治”的水稻田管原则,广泛宣传,科学指导,多措并举,扎实开展水稻病虫害综合防治</p>
|
45 |
+
</div>
|
46 |
+
</div>
|
47 |
+
<div class="row mb-2">
|
48 |
+
<div class="col-md-6">
|
49 |
+
<div class="row g-0 border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
|
50 |
+
<div class="col p-4 d-flex flex-column position-static">
|
51 |
+
<strong class="d-inline-block mb-2 text-primary">世界</strong>
|
52 |
+
<h3 class="mb-0">农业产业绿色振兴</h3>
|
53 |
+
<div class="mb-1 text-muted">08/01</div>
|
54 |
+
<p class="card-text mb-auto">如何充分发挥科技兴农作用、怎样有效促进产业绿色振兴,无疑是新时代赋予农业科研院所与科技人员的...</p>
|
55 |
+
<a href="{{ url_for("article", value="1") }}" class="stretched-link">继续阅读</a>
|
56 |
+
</div>
|
57 |
+
<div class="col-md-4" style="background: url('/static/images/articles/绿色产业.jpg') no-repeat center;background-size: cover">
|
58 |
+
</div>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
<div class="col-md-6">
|
62 |
+
<div class="row g-0 border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">
|
63 |
+
<div class="col p-4 d-flex flex-column position-static">
|
64 |
+
<strong class="d-inline-block mb-2 text-success">科学</strong>
|
65 |
+
<h3 class="mb-0">如何进行科学施肥</h3>
|
66 |
+
<div class="mb-1 text-muted">01/14</div>
|
67 |
+
<p class="mb-auto">对农作物施肥一直是农业生产中重要的环节,其好坏决定着农作物的生长情况,那究竟该如何进行科学的施肥呢?下面就...</p>
|
68 |
+
<a href="{{ url_for("article", value="2") }}" class="stretched-link">继续阅读</a>
|
69 |
+
</div>
|
70 |
+
<div class="col-md-4" style="background: url('/static/images/articles/科学施肥.jpg') no-repeat center;background-size: cover">
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
</div>
|
75 |
+
</main>
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
{% endblock %}
|
detectweb/templates/intros/intro_apple.html
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!doctype html>
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="utf-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7 |
+
<meta name="description" content="">
|
8 |
+
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
|
9 |
+
<meta name="generator" content="Hugo 0.80.0">
|
10 |
+
<title>Intro example</title>
|
11 |
+
|
12 |
+
|
13 |
+
<!-- Bootstrap core CSS -->
|
14 |
+
<link href="/static/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
15 |
+
|
16 |
+
<style>
|
17 |
+
.bd-placeholder-img {
|
18 |
+
font-size: 1.125rem;
|
19 |
+
text-anchor: middle;
|
20 |
+
-webkit-user-select: none;
|
21 |
+
-moz-user-select: none;
|
22 |
+
user-select: none;
|
23 |
+
}
|
24 |
+
|
25 |
+
@media (min-width: 768px) {
|
26 |
+
.bd-placeholder-img-lg {
|
27 |
+
font-size: 3.5rem;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
</style>
|
31 |
+
</head>
|
32 |
+
|
33 |
+
<body>
|
34 |
+
<main>
|
35 |
+
<section class="py-5 text-center container" style="background: url('/static/images/apple/apple.jpg') no-repeat center;background-size: cover">
|
36 |
+
<div class="row py-lg-5">
|
37 |
+
<div class="col-lg-6 col-md-8 mx-auto">
|
38 |
+
<h1 class="fw-light">苹果篇</h1>
|
39 |
+
<p class="lead text-white">
|
40 |
+
苹果是蔷薇科苹果亚科苹果属植物,其树为落叶乔木。苹果营养价值很高,富含矿物质和维生素,含钙量丰富,有助于代谢掉体内多余盐分,苹果酸可代谢热量,防止下半身肥胖。
|
41 |
+
<br><br>
|
42 |
+
苹果是一种低热量的食物,每100克产生大约60千卡左右的热量。苹果中营养成分可溶性大,容易被人体吸收,故有“活水”之称。它有利于溶解硫元素,使皮肤润滑柔嫩。
|
43 |
+
</p>
|
44 |
+
</div>
|
45 |
+
</div>
|
46 |
+
</section>
|
47 |
+
|
48 |
+
<div class="album py-5 bg-light">
|
49 |
+
<div class="container">
|
50 |
+
<div class="row featurette">
|
51 |
+
<div class="col-md-8">
|
52 |
+
<h2 class="featurette-heading">种植技术</h2>
|
53 |
+
<p class="lead" style="font-size:16px">
|
54 |
+
苹果树是喜低温干燥的温带果树,要求冬无严寒,夏无酷暑。适宜的温度范围是年平均气温9~14℃,冬季极端低温不低于-12℃,夏季最高月均温不高于20℃,≥10℃年积温5000℃左右,生长季节(4~10月)平均气温12~18℃,冬季需7.2℃以下低温1200~1500小时,才能顺利通过自然休眠。一般认为年平均温度在7.5~14℃的地区,都可以栽培苹果。苹果自然休眠期较长。如冬季温度高,不能满足冬季休眠期所需低温时,春季发芽不齐。
|
55 |
+
</p>
|
56 |
+
<p class="lead" style="font-size:16px">
|
57 |
+
从世界栽培苹果最多地区来看,冬季最冷月(北半球1月,南半球7月)平均气温在-10~10℃之间,才能满足苹果对低温的要求。中国各苹果主要产区的一月份平均气温都在此限度内。生长期(4~10月)平均气温在12~18℃,夏季(6~8月)平均气温在18~24℃,最适合苹果的生长。秋季温度,白天高夜间低时,果实含糖分高,着色好,果皮厚,果粉多,耐贮藏。
|
58 |
+
</p>
|
59 |
+
<p class="lead" style="font-size:16px">
|
60 |
+
苹果在生长期每亩地需降水量约为180毫米。一般自然降水量,实际能利用到果树吸收的约为1/3,这样生长期降水量能有540毫米,已足够用。在4~9月降水量在450毫米以下的地区则需要灌水,中国北方降水量分布不均,70%~80%集中在7~8月间,春季则水量不足。在内陆降水量少的地区,水量不足,因此在建园选地时,必须考虑到灌溉条件和保墒措施,同时也要注意雨季排水措施。
|
61 |
+
</p>
|
62 |
+
<p class="lead" style="font-size:16px">
|
63 |
+
苹果树是喜光树种,光照充足,才能生长正常。据山东农大测定,泰安地区金冠、新红星,光照补偿点为600~800米烛光,饱和点在3500~4500米烛光。在此范围内光照强度增加,光合作用也加强。日照不足,则引起一系列反应,如枝叶徒长、软弱、抗病虫力差,花芽分化少,营养贮存少,开花座果率低,根系生长也受影响,果实含糖量低,上色也不好。
|
64 |
+
</p>
|
65 |
+
<p class="lead" style="font-size:16px">
|
66 |
+
土壤对苹果的生长、产量、质量的好坏影响很大。主要因素是土层、土壤通气、土质。总之,苹果需要土壤肥沃深厚,排水良好,含丰富有机质,微酸性到微碱性。大风常给苹果的生长发育带来许多不利的影响,如造成树冠偏斜,影响开花,授粉,破坏叶器官,以及落果等,所以在风大地区建立苹果园,必须营造防风林。
|
67 |
+
</p>
|
68 |
+
</div>
|
69 |
+
<div class="col-md-4" style="background: url('/static/images/apple/种植技术.jpg') no-repeat center;background-size: cover">
|
70 |
+
</div>
|
71 |
+
</div>
|
72 |
+
|
73 |
+
<hr class="featurette-divider">
|
74 |
+
<hr class="featurette-divider">
|
75 |
+
|
76 |
+
<div class="row featurette">
|
77 |
+
<div class="col-md-8 order-md-2">
|
78 |
+
<h2 class="featurette-heading">病害防治 —— 腐烂病</h2>
|
79 |
+
<p class="lead" style="font-size:16px">
|
80 |
+
症状表现:该病病原为苹果黑腐皮壳菌,每年的3~4月是发病高峰。主要危害苹果的枝干,可表现出溃疡与枝枯两种类型,并以前者为主。发病初期,病部呈红褐色湿腐状,微微隆起,有酒糟味。后期病部失水干缩,变成黑褐色。
|
81 |
+
<br><br>
|
82 |
+
防治方法:预防上具体做好清园、保护剪口、勤防病虫、增施有机肥等工作,可有效提高树势,降低病原基数。对于已发病的,应及时刮除病部,涂抹氟硅唑、戊唑醇等药剂治疗保护,降低复发率。
|
83 |
+
</p>
|
84 |
+
</div>
|
85 |
+
<div class="col-md-4" style="background: url('/static/images/apple/腐烂病.jpg') no-repeat center;background-size: cover">
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
|
89 |
+
<hr class="featurette-divider">
|
90 |
+
|
91 |
+
<div class="row featurette">
|
92 |
+
<div class="col-md-8">
|
93 |
+
<h2 class="featurette-heading">病害防治 —— 轮纹病</h2>
|
94 |
+
<p class="lead" style="font-size:16px">
|
95 |
+
症状表现:该病主要集中在5~8月,遇连续降雨、田间湿度大时易发病。主要危害枝干和果实,枝干受害,初期会密生圆形疣状凸起,后相连成片失水凹陷,病健交界明显;果实受害,初期在皮孔周围形成褐色或黄褐色小斑点,随后病斑扩展成圆形或近圆形同心轮纹,并外渗出黄褐色液体。
|
96 |
+
<br><br>
|
97 |
+
防治方法:由于侵染果实的轮纹病菌主要源于树体枝干,所以要注意刮除病斑、剪除病枝。病菌孢子散发高峰期,在刮除病部后,用吡唑醚菌酯、戊唑醇等处理病部。
|
98 |
+
</p>
|
99 |
+
</div>
|
100 |
+
<div class="col-md-4" style="background: url('/static/images/apple/轮纹病.jpg') no-repeat center;background-size: cover">
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
|
104 |
+
<hr class="featurette-divider">
|
105 |
+
|
106 |
+
<div class="row featurette">
|
107 |
+
<div class="col-md-8 order-md-2">
|
108 |
+
<h2 class="featurette-heading">病害防治 —— 褐斑病</h2>
|
109 |
+
<p class="lead" style="font-size:16px">
|
110 |
+
症状表现:每年5~7月是该病侵染发病期,多雨高温会诱发该病的大发生。主要危害苹果叶片,症状有绿缘褐斑型、同心轮纹型、针芒型、混合型、褐点型病斑等多种类型,一般为害树冠下部或内膛的叶片,新叶很少发病,病叶极易脱落。
|
111 |
+
<br><br>
|
112 |
+
防治方法:生产上多采用药剂进行防治,药剂可选择氟环唑、戊唑醇等,发病重的苹果园可配伍多抗锰锌。
|
113 |
+
</p>
|
114 |
+
</div>
|
115 |
+
<div class="col-md-4" style="background: url('/static/images/apple/褐斑病.jpg') no-repeat center;background-size: cover">
|
116 |
+
</div>
|
117 |
+
</div>
|
118 |
+
|
119 |
+
<hr class="featurette-divider">
|
120 |
+
|
121 |
+
<div class="row featurette">
|
122 |
+
<div class="col-md-8">
|
123 |
+
<h2 class="featurette-heading">病害防治 —— 炭疽病</h2>
|
124 |
+
<p class="lead" style="font-size:16px">
|
125 |
+
症状表现:该病主要危害叶片和果实,一般5月后可见发病,遇连续降雨病情发展迅速。叶片发病时,初期在叶面上形成黑色坏死病斑,病斑与健部边缘模糊,随后病斑开始蔓延,连接成片,造成叶片焦枯;果实发病时,轮纹状病斑,潮湿时有红色黏液析出。
|
126 |
+
<br><br>
|
127 |
+
防治方法:药剂可选择甲硫·戊唑醇、咪鲜胺、溴菌腈等,要注意前期的清园及初侵染期的防治,否则进入雨季病害将难以控制。
|
128 |
+
</p>
|
129 |
+
</div>
|
130 |
+
<div class="col-md-4" style="background: url('/static/images/apple/炭疽病.jpg') no-repeat center;background-size: cover">
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
|
134 |
+
<hr class="featurette-divider">
|
135 |
+
|
136 |
+
<div class="row featurette">
|
137 |
+
<div class="col-md-8 order-md-2">
|
138 |
+
<h2 class="featurette-heading">病害防治 —— 白粉病</h2>
|
139 |
+
<p class="lead" style="font-size:16px">
|
140 |
+
症状表现:可危害新梢、叶片、花、幼果等。变现为枯梢、新梢卷曲、叶果生白色粉层,花果畸形等。春季温暖干旱、夏季多雨凉爽等有利于该病的发生流行。
|
141 |
+
<br><br>
|
142 |
+
防治方法:萌芽前,花露红期,谢花80%时,落花后10~15天,套袋前是重点防控期,药剂可选择石硫合剂(清园)、氟硅唑、三唑酮、吡唑醚菌酯、代森锰锌等。
|
143 |
+
</p>
|
144 |
+
</div>
|
145 |
+
<div class="col-md-4" style="background: url('/static/images/apple/白粉病.jpg') no-repeat center;background-size: cover">
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
</div>
|
149 |
+
</div>
|
150 |
+
</main>
|
151 |
+
|
152 |
+
|
153 |
+
<script src="/static/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
|
154 |
+
</body>
|
155 |
+
</html>
|
detectweb/templates/intros/intro_cherry.html
ADDED
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!doctype html>
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="utf-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7 |
+
<meta name="description" content="">
|
8 |
+
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
|
9 |
+
<meta name="generator" content="Hugo 0.80.0">
|
10 |
+
<title>Intro example</title>
|
11 |
+
|
12 |
+
|
13 |
+
<!-- Bootstrap core CSS -->
|
14 |
+
<link href="/static/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
15 |
+
|
16 |
+
<style>
|
17 |
+
.bd-placeholder-img {
|
18 |
+
font-size: 1.125rem;
|
19 |
+
text-anchor: middle;
|
20 |
+
-webkit-user-select: none;
|
21 |
+
-moz-user-select: none;
|
22 |
+
user-select: none;
|
23 |
+
}
|
24 |
+
|
25 |
+
@media (min-width: 768px) {
|
26 |
+
.bd-placeholder-img-lg {
|
27 |
+
font-size: 3.5rem;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
</style>
|
31 |
+
</head>
|
32 |
+
|
33 |
+
<body>
|
34 |
+
<main>
|
35 |
+
<section class="py-5 text-center container" style="background: url('/static/images/cherry/cherry.png') no-repeat center;background-size: cover">
|
36 |
+
<div class="row py-lg-5">
|
37 |
+
<div class="col-lg-6 col-md-8 mx-auto">
|
38 |
+
<h1 class="fw-light">樱桃篇</h1>
|
39 |
+
<p class="lead text-white">乔木,高2-6米,树皮灰白色。小枝灰褐色,嫩枝绿色,无毛或被疏柔毛。花序伞房状或近伞形,有花3-6朵,先叶开放;雄蕊30-35枚,栽培者可达50枚。花柱与雄蕊近等长,无毛。核果近球形,红色,直径0.9-1.3厘米。花期3-4月,果期5-6月</p>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
</section>
|
43 |
+
|
44 |
+
<div class="album py-5 bg-light">
|
45 |
+
<div class="container">
|
46 |
+
<div class="row featurette">
|
47 |
+
<div class="col-md-8">
|
48 |
+
<h2 class="featurette-heading">种植技术</h2>
|
49 |
+
<p class="lead" style="font-size:16px">
|
50 |
+
樱桃理想的露地栽培区的年平均气温应为7-14℃,一年中日平均温度高于10℃的天数至少在150-200天之间。樱桃越冬休眠期的临界低温不得低于是-20℃。当气温达到-20℃以下时就发生冻害。樱桃发芽期适宜的温度为10℃,开花期适宜温度为15℃,樱桃显蕾后抗寒力降低,花蕾期发生冻害的临界温度为1.7℃,在-3℃下4小时花蕾会100%受冻。25℃左右时花粉会失去活力。果实发育到成熟期适宜温度为20℃。开花和幼果发育期冻害的临界温度为-1.1℃。甜樱桃萌芽至开花期需要10℃以上的温度总量为446℃,开花至成熟需要20℃以上温度总量为446℃。
|
51 |
+
</p>
|
52 |
+
<p class="lead" style="font-size:16px">
|
53 |
+
樱桃是一种喜水又不耐水淹的果树。樱桃根系分布比较浅,抗旱能力差,但其叶片大,蒸滕作用强,所以需要较多的水份供应,故有“樱桃不离水”的俗语。一般地说樱桃适于年降水量600-800mm的地区生长。有灌溉设施的果园不受年降水量影响。如果土壤含水量下降到11-12%时就会引起大量落果;下降到10%左右时地上部分就停止生气;下降到7%时,叶片发生萎蔫。樱桃的根系要求良好的通透气体条件,果园积水时,土壤的含氧量减少,就会引起根系窒息而引起烂根、流胶,甚至引起整树死亡。所以樱桃园要建在排水良好的地方,园内要起垅栽种,以便随时排除园内的渍水。
|
54 |
+
</p>
|
55 |
+
<p class="lead" style="font-size:16px">
|
56 |
+
樱桃在土层深厚,质地疏松、肥力较高的砾质壤土、沙壤土、壤土或轻粘土壤中,根分布较深,根系发达,生长健壮。在粘重土壤上,根系发育不良,导致植株生长不良。当土壤有机质含量达到12%时,樱桃栽后2年就开始结果,4年就可丰产,最高亩产可达2000kg以上,优质果品率高。当土壤有机质含量低于1%时,果个小、味道差、产量低,很难生产出优质果品。樱桃要求土壤为接近中性的土壤。樱桃对盐碱地比较敏感,在这种土壤上轻者生长不良,易感缺素症,重者死亡。
|
57 |
+
</p>
|
58 |
+
</div>
|
59 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/cherry1.jpg') no-repeat center;background-size: cover">
|
60 |
+
</div>
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<hr class="featurette-divider">
|
64 |
+
|
65 |
+
<div class="row featurette">
|
66 |
+
<div class="col-md-8 order-md-2">
|
67 |
+
<h2 class="featurette-heading">生育期</h2>
|
68 |
+
<p class="lead" style="font-size:16px">
|
69 |
+
樱桃树生育期亩施肥量氮肥(N)13-15公斤、磷肥(P2O5)5-7公斤、钾肥(K2O) 7-9公斤。樱桃从展叶、抽梢、开花结果到成熟,都集中在生长季节的前半期,而花芽分化又在果实采收后的较短的时间内完成,具有生长发育迅速、需肥集中的特点。座果前的生长发育主要是利用冬前树体贮藏的养分,冬前树体贮藏的养分多少及分配对樱桃早春枝叶生长,开花坐果和果实膨大有很大影响。樱桃从展叶到果实成熟前需肥量最大;采果后花芽分化盛期需肥量次之;其余时间需肥量较少。因此,重点抓好秋施基肥和花期、采收后两次追肥。不同树龄需肥特点。<br>
|
70 |
+
1、3年生以下的幼树,应以氮肥为主,辅助适量的磷、钾肥。促树枝干早形成,早结果。<br>
|
71 |
+
2、4-6年生为初果期幼树,既长枝干又结果,由营养生长到生殖生长的转化。在施肥上要注意控氮、增磷、钾,补钙及中微量营养元素。<br>
|
72 |
+
3、7年生以上的树进入盛果期,需要增施氮、磷、钾,在樱桃果实生长阶段补充钾、钙、中微量营养,可大幅提高果实的产量与品质。
|
73 |
+
</p>
|
74 |
+
</div>
|
75 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/cherry2.jfif') no-repeat center;background-size: cover">
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
|
79 |
+
<hr class="featurette-divider">
|
80 |
+
<hr class="featurette-divider">
|
81 |
+
|
82 |
+
<div class="row featurette">
|
83 |
+
<div class="col-md-8">
|
84 |
+
<h2 class="featurette-heading">病害防治 —— 樱桃褐腐病</h2>
|
85 |
+
<p class="lead" style="font-size:16px">
|
86 |
+
主要为害花和果实,引起花腐和果腐,发病初期,花器渐变褐色,直至干枯;后期病部形成一层灰褐色粉状物,从落花后10天幼果开始发病,果面上形成浅褐色小斑点,逐渐推广为黑褐色病斑,幼果不软腐,成熟果发病,初期在果面产生浅褐色小斑点,迅速推广,引起全果软腐。
|
87 |
+
<br><br>
|
88 |
+
防治措施:①清洁果园,将落叶、落果清扫烧毁;②合理修剪,使树冠具有良好的通风透光条件;③发芽前喷1次3-5度石硫合剂;④生长季每隔10-15天喷1次药,共喷4-6次,药剂可用1:2:240倍波尔多液或77%可杀得500倍液,50%克菌丹500倍液。
|
89 |
+
</p>
|
90 |
+
</div>
|
91 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/樱桃褐腐病.png') no-repeat center;background-size: cover">
|
92 |
+
</div>
|
93 |
+
</div>
|
94 |
+
|
95 |
+
<hr class="featurette-divider">
|
96 |
+
|
97 |
+
<div class="row featurette">
|
98 |
+
<div class="col-md-8 order-md-2">
|
99 |
+
<h2 class="featurette-heading">病害防治 —— 樱桃流胶病</h2>
|
100 |
+
<p class="lead" style="font-size:16px">
|
101 |
+
主要为害樱桃主干和主枝,一般从春季树液流动时开始发生,初期枝干的枝杈处或伤口肿胀,流出黄白色半透明的粘质物,皮层及木质部变褐腐朽,导致树势衰弱,严重时枝干枯死。发病原因一是有枝干病害、虫害、冻害、机械伤造成的伤口引起流胶,二是由于修剪过度、施肥不当、水分过多、土壤理化性状不良等,导致树体生理代谢失调而引起流胶。
|
102 |
+
<br><br>
|
103 |
+
防治措施:①增施有机肥,健壮树势,防止旱、涝、冻害;②搞好病虫害防治,避免造成过多伤口;③冬剪最好在树液流动前进行,夏季尽量减少较大的剪锯口;④发现流胶病,要及时刮除,然后涂药保护。常用药剂有50%退菌特1份、50%悬浮硫5份加水调成混合液,以及用生石灰10份、石硫合剂1份、食盐2份、植物油0.3份加水调成混合液。
|
104 |
+
</p>
|
105 |
+
</div>
|
106 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/樱桃流胶病.png') no-repeat center;background-size: cover">
|
107 |
+
</div>
|
108 |
+
</div>
|
109 |
+
|
110 |
+
<hr class="featurette-divider">
|
111 |
+
|
112 |
+
<div class="row featurette">
|
113 |
+
<div class="col-md-8">
|
114 |
+
<h2 class="featurette-heading">病害防治 —— 樱桃叶斑病</h2>
|
115 |
+
<p class="lead" style="font-size:16px">
|
116 |
+
该病主要为害叶片,也为害叶柄和果实。叶片发病初期,在叶片正面叶脉间产生紫色或褐色的坏死斑点,同时在斑点的背面形成粉红色霉状物,后期随着斑点的扩大,数斑联合使叶片大部分枯死。有时叶片也形成穿孔现象,造成叶片早期脱落,叶片一般5月份开始发病,7-8月份高温、多雨季节发病严重。
|
117 |
+
<br><br>
|
118 |
+
防治措施:①加强栽培,增强树势,提高树体抗病能力;②清除病枝、病叶,集中烧毁或深埋;③发芽前喷3-5度石硫合剂;④谢花后至采果前,喷1-2次70%代森锰锌600倍液或75%百菌清500-600倍液,大生M-45800倍液等,每隔10-14天喷1次。
|
119 |
+
</p>
|
120 |
+
</div>
|
121 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/樱桃叶斑病.png') no-repeat center;background-size: cover">
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
|
125 |
+
<hr class="featurette-divider">
|
126 |
+
<hr class="featurette-divider">
|
127 |
+
|
128 |
+
<div class="row featurette">
|
129 |
+
<div class="col-md-8 order-md-2">
|
130 |
+
<h2 class="featurette-heading">虫害防治 —— 绣线菊蚜</h2>
|
131 |
+
<p class="lead" style="font-size:16px">
|
132 |
+
一年发生10余代,主要以卵在樱桃枝条芽旁或树皮裂缝处越冬,翌年4月上中旬萌芽时卵开始孵化,初孵幼蚜群集在叶背面取食,10天左右即产生无翅胎生雌蚜,6-7月温度升高,繁殖加快,虫口密度迅速增长,为害严重。8-9月蚜群数量开始减少,10月开始产生有性蚜虫,雌雄交尾产卵,以卵越冬。
|
133 |
+
<br><br>
|
134 |
+
防治措施:①展叶前,越冬卵孵化基本结束时,喷40%乐果或70%灭蚜可湿性粉剂1500-2000倍液;②5月上旬蚜虫初发期进行药剂涂干,如树皮粗糙,先将粗皮刮去,刮至稍露白即可;常用内吸药剂有40%乐果乳油2-3倍液,在主干中部用毛刷涂成6cm的环带。如蚜虫较多,10天后可在原部位再涂药1次;③有条件的可人工饲养捕食性瓢虫、草蛉等天敌。
|
135 |
+
</p>
|
136 |
+
</div>
|
137 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/绣线菊蚜.png') no-repeat center;background-size: cover">
|
138 |
+
</div>
|
139 |
+
</div>
|
140 |
+
|
141 |
+
<hr class="featurette-divider">
|
142 |
+
|
143 |
+
<div class="row featurette">
|
144 |
+
<div class="col-md-8">
|
145 |
+
<h2 class="featurette-heading">虫害防治 —— 舟形毛虫</h2>
|
146 |
+
<p class="lead" style="font-size:16px">
|
147 |
+
一年发生1代,以蛹在树根部土层内越冬,第2年7月上旬至8月中旬羽化成虫,昼伏夜出,趋光性较强,卵多产在叶背面。3龄前的幼虫群集在叶背为害,早晚及夜间为害,静止的幼虫沿叶缘整齐排列,头、尾上翘,若遇振动,则成群吐丝下垂,9月份幼虫老熟后入土化蛹越冬。
|
148 |
+
<br><br>
|
149 |
+
防治措施:①结合秋翻地或春刨树盘,使越冬蛹暴露地面失水而死;②利用3龄前群集取食和受惊下垂习性,进行人工摘除有虫群集的枝叶;③为害期可喷50%杀螟松乳油1000倍液或20%速灭杀丁2000倍液。
|
150 |
+
</p>
|
151 |
+
</div>
|
152 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/舟形毛虫.png') no-repeat center;background-size: cover">
|
153 |
+
</div>
|
154 |
+
</div>
|
155 |
+
|
156 |
+
<hr class="featurette-divider">
|
157 |
+
|
158 |
+
<div class="row featurette">
|
159 |
+
<div class="col-md-8 order-md-2">
|
160 |
+
<h2 class="featurette-heading">虫害防治 —— 桑白蚧</h2>
|
161 |
+
<p class="lead" style="font-size:16px">
|
162 |
+
为害状多以若虫和雌成虫群集枝条上吸食,2-3年生枝受害最重,被害处稍凹陷
|
163 |
+
<br><br>
|
164 |
+
防治方法:①人工防治冬季休眠期,人工刮刷树皮,消灭越冬雌成虫。②休眠期药剂防治萌芽期,喷布1次5%蒽油乳剂,或5波美度石硫合剂。③生长期药剂防治各代若虫孵化盛期喷布1次40%乐果乳油1500倍液,或50%敌敌畏乳油1000倍液,或2.5%功夫乳油3000倍液。④生物防治小黑瓢虫是重要天敌,应保护利用。
|
165 |
+
</p>
|
166 |
+
</div>
|
167 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/桑白蚧.png') no-repeat center;background-size: cover">
|
168 |
+
</div>
|
169 |
+
</div>
|
170 |
+
|
171 |
+
<hr class="featurette-divider">
|
172 |
+
|
173 |
+
<div class="row featurette">
|
174 |
+
<div class="col-md-8">
|
175 |
+
<h2 class="featurette-heading">虫害防治 —— 红颈天牛</h2>
|
176 |
+
<p class="lead" style="font-size:16px">
|
177 |
+
为害状初孵幼虫先在枝干的皮下蛀食,虫孔排列个整齐。第二年,大龄幼虫深入到木质部蛀食,蛀成孔道,并从蛀孔向外排泄锯末样的红褐色虫类。
|
178 |
+
<br><br>
|
179 |
+
防治方法:①人工防治小幼虫在皮下为害期间,发现虫粪,即人工挖除;或用兽用针管注射80%敌敌畏乳油800倍液,或50%辛硫磷乳油500液,注入虫道后,用泥封堵药杀。此外还可人工辅杀成虫。②忌避防治成虫羽化前,在枝干上涂刷用10份生石灰、1份硫磺以及40份水调制而成的白涂剂,防止成虫产卵。
|
180 |
+
</p>
|
181 |
+
</div>
|
182 |
+
<div class="col-md-4" style="background: url('/static/images/cherry/红颈天牛.png') no-repeat center;background-size: cover">
|
183 |
+
</div>
|
184 |
+
</div>
|
185 |
+
</div>
|
186 |
+
</div>
|
187 |
+
</main>
|
188 |
+
<script src="/static/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
|
189 |
+
</body>
|
190 |
+
</html>
|
detectweb/templates/intros/intro_corn.html
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<!doctype html>
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="utf-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
7 |
+
<meta name="description" content="">
|
8 |
+
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
|
9 |
+
<meta name="generator" content="Hugo 0.80.0">
|
10 |
+
<title>Intro example</title>
|
11 |
+
|
12 |
+
|
13 |
+
<!-- Bootstrap core CSS -->
|
14 |
+
<link href="/static/docs/5.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
|
15 |
+
|
16 |
+
<style>
|
17 |
+
.bd-placeholder-img {
|
18 |
+
font-size: 1.125rem;
|
19 |
+
text-anchor: middle;
|
20 |
+
-webkit-user-select: none;
|
21 |
+
-moz-user-select: none;
|
22 |
+
user-select: none;
|
23 |
+
}
|
24 |
+
|
25 |
+
@media (min-width: 768px) {
|
26 |
+
.bd-placeholder-img-lg {
|
27 |
+
font-size: 3.5rem;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
</style>
|
31 |
+
</head>
|
32 |
+
|
33 |
+
<body>
|
34 |
+
<main>
|
35 |
+
<section class="py-5 text-center container" style="background: url('/static/images/corn/corn.png') no-repeat center;background-size: cover">
|
36 |
+
<div class="row py-lg-5">
|
37 |
+
<div class="col-lg-6 col-md-8 mx-auto">
|
38 |
+
<h1 class="fw-light">玉米篇</h1>
|
39 |
+
<p class="lead text-white">
|
40 |
+
玉米(Zea mays L.)是禾本科的一年生草本植物。又名苞谷、苞米棒子、玉蜀黍、珍珠米等。原产于中美洲和南美洲,它是世界重要的粮食作物,广泛分布于美国、中国、巴西和其他国家。 玉米与传统的水稻、小麦等粮食作物相比,玉米具有很强的耐旱性、耐寒性、耐贫瘠性以及极好的环境适应性。玉米的营养价值较高,是优良的粮食作物。作为中国的高产粮食作物,玉米是畜牧业、养殖业、水产养殖业等的重要饲料来源,也是食品、医疗卫生、轻工业、化工业等的不可或缺的原料之一。由于玉米资源极为丰富、廉价且易于获得,它们还具有许多生物活性,如抗氧化、抗肿瘤、降血糖、提高免疫力和抑菌杀菌等,其具有广阔的开发及应用前景。
|
41 |
+
</p>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</section>
|
45 |
+
|
46 |
+
<div class="album py-5 bg-light">
|
47 |
+
<div class="container">
|
48 |
+
<div class="row featurette">
|
49 |
+
<div class="col-md-8">
|
50 |
+
<h2 class="featurette-heading">种植技术</h2>
|
51 |
+
<p class="lead" style="font-size:16px">
|
52 |
+
【选用优良品种】精选优质良种,一般选用具有高产潜力、耐密紧凑、大穗型的中晚熟品种,保证抗倒性比较强、抗病性能好。抗倒性强的品种茎秆坚硬、根系发达。抗病性强的品种高群体下抗叶斑病,如东疏镇种植的郑单958、农大108、登海9号、鲁单981等。选用包衣的良种,种子纯度高于96%,出芽率高于85%,净度高于98%。若实行单粒精播,种子出芽率应在94%以上。 精细播种随着机械化程度的提高,为玉米套种改直播创造了条件,同时也有利于推广玉米机械化播种,保证一播全苗,苗匀苗壮,提高均匀性、整齐度。适宜播种期为6月5-15日,一般播种45.0-52.5kg/hm2,单粒播7.50万-8.25万粒/hm2。采用单粒点播机进行精量直播,一次完成施肥、播种,行距65cm,株距18cm,播种深度为5cm,播种后根据土壤墒情及时浇水。
|
53 |
+
<br>选用耐密型品种,在中等肥力地块定苗控制为6万株/hm2,如农大108和登海9号等大穗型品种;在高肥力地块定苗控制为6.75万株/hm2,如郑单958等品种;高产攻关田、示范田还要适当增加种植密度。
|
54 |
+
<br>套种玉米采用直播方式,要缩短玉米与小麦的共生期,尽量避免出现弱小苗。苗期需控制氮肥用量,增施磷、钾肥和有机肥;另外,根据需要控制浇水,夏玉米生长期降雨与生长需水同步,除田间持水量小于55%外,各生育期一般不用浇水。定苗防止过密,大穗型品种一般不能超过6万株/hm2,中穗型不能超过8.25万株/hm2,高密度容易造成空秆、病害重、倒伏等问题,导致中后期管理困难,影响产量。
|
55 |
+
</p>
|
56 |
+
<p class="lead" style="font-size:16px">
|
57 |
+
【定苗】玉米在三叶期丛苗疏开,5叶时可按株距定苗,要拔除病苗、弱苗、异株,留健壮苗;若遇缺苗断垄的地方,相邻处要留双株补苗。
|
58 |
+
</p>
|
59 |
+
<p class="lead" style="font-size:16px">
|
60 |
+
【土肥水管理】定苗后及时中耕,清垄灭茬,促进根部下扎。其中,���倒的关键性措施是增施钾肥、苗期控水和防止过密。玉米根深才能株壮和抗倒能力强,土壤旋耕2-3年后要深翻1次。深松土壤35cm,分次施氮肥,增施有机肥。
|
61 |
+
<br>在测土掌握地力的基础上,根据目标产量9000kg/hm2以上,施肥量为速效氮150kg/hm2以上、速效磷60kg/hm2以上、速效钾75kg/hm2以上,有条件的增施硫酸锌22.5kg/hm2作底肥。
|
62 |
+
<br>肥料运筹为轻施苗肥、重施穗肥、补追花粒肥。苗肥在玉米拔节前沿幼苗一侧开沟,将全部磷、钾、硫、锌肥与氮肥总量的30%左右深施15-20cm,以促根壮苗;在玉米大喇叭口期(叶龄指数55%-60%,第11-12片叶展开)重施穗肥,追施控制在总氮量的50%,以促进穗大粒多;在籽粒灌浆期追施花粒肥,控制在总氮量的20%,以增加千粒重、增强叶片的光合作用。施肥方式为沟施或穴施,施后埋土浇水,以提高肥料利用率。水分管理上,应均匀灌溉,推荐小畦隔沟交替灌溉的节水技术;全生育期在110d左右,要求玉米播种后苗期、抽雄开花期、灌浆成熟期土壤相对含水量在80%以上,确保光热资源充足。
|
63 |
+
</p>
|
64 |
+
<p class="lead" style="font-size:16px">
|
65 |
+
【适时收获】与贮藏夏玉米适宜收获期为9月底至10月初。当苞叶干枯,籽粒乳线消失、黑层出现且含水量低于32%时,选用机械收获,秸秆粉碎还田,培肥地力。大量实践证明,玉米晚收可增产750-1500kg/hm2,千粒重增加15%以上。当籽粒含水量小于14%时,选择干燥通风的场地贮藏。
|
66 |
+
</p>
|
67 |
+
</div>
|
68 |
+
<div class="col-md-4" style="background: url('/static/images/corn/种植技术.jpg') no-repeat center;background-size: cover">
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
|
72 |
+
<hr class="featurette-divider">
|
73 |
+
<hr class="featurette-divider">
|
74 |
+
|
75 |
+
<div class="row featurette">
|
76 |
+
<div class="col-md-8 order-md-2">
|
77 |
+
<h2 class="featurette-heading">病害防治 —— 纹枯病</h2>
|
78 |
+
<p class="lead" style="font-size:16px">
|
79 |
+
纹枯病主要发生在玉米生长后期,即籽粒形成期至灌浆期,该病主要为害玉米的叶鞘、果穗和茎秆。
|
80 |
+
<br><br>
|
81 |
+
发病初期,每亩用5%井岗霉素100―150毫升,兑水50―60公斤,对准发病部位均匀喷雾。可在玉米大喇叭口期,每亩用5%井冈霉素可溶性粉剂200克,拌无菌细土20―25公斤撮施于玉米大喇叭口内,这种办法不仅防效高,成本低,持效期长,简便易行。采用井冈霉素毒土1次性撮施于心叶,不仅能防治纹枯病,还可兼治玉米穗腐病。
|
82 |
+
</p>
|
83 |
+
</div>
|
84 |
+
<div class="col-md-4" style="background: url('/static/images/corn/纹枯病.jfif') no-repeat center;background-size: cover">
|
85 |
+
</div>
|
86 |
+
</div>
|
87 |
+
|
88 |
+
<hr class="featurette-divider">
|
89 |
+
|
90 |
+
<div class="row featurette">
|
91 |
+
<div class="col-md-8">
|
92 |
+
<h2 class="featurette-heading">病害防治 —— 穗腐病</h2>
|
93 |
+
<p class="lead" style="font-size:16px">
|
94 |
+
玉米穗腐病主要在果穗和籽粒上发病,被害果穗顶部或中部变色,并出现粉红色、蓝绿色、黑灰色或暗褐色、黄褐色霉层。
|
95 |
+
<br><br>
|
96 |
+
药剂防治措施:抽穗期用50%多菌灵可湿性粉剂或50%甲基托布津可湿性粉剂1000倍液喷雾。重点喷果穗及下部茎叶,隔7天再喷1次。
|
97 |
+
</p>
|
98 |
+
</div>
|
99 |
+
<div class="col-md-4" style="background: url('/static/images/corn/穗腐病.png') no-repeat center;background-size: cover">
|
100 |
+
</div>
|
101 |
+
</div>
|
102 |
+
|
103 |
+
<hr class="featurette-divider">
|
104 |
+
|
105 |
+
<div class="row featurette">
|
106 |
+
<div class="col-md-8 order-md-2">
|
107 |
+
<h2 class="featurette-heading">病害防治 —— 青枯病</h2>
|
108 |
+
<p class="lead" style="font-size:16px">
|
109 |
+
青枯病又叫茎腐病或茎基腐病,一般在玉米灌浆期开始发病,乳熟末期至蜡熟期为高峰期,常发生在暴风雨过后。
|
110 |
+
<br><br>
|
111 |
+
药剂防治措施:在发病严重地块,用25%叶枯灵或20%叶枯净可湿性粉剂加25%���毒霉可湿性粉剂或5%瑞毒霉锰锌可湿性粉剂600倍液叶面喷施。
|
112 |
+
</p>
|
113 |
+
</div>
|
114 |
+
<div class="col-md-4" style="background: url('/static/images/corn/青枯病.jpg') no-repeat center;background-size: cover">
|
115 |
+
</div>
|
116 |
+
</div>
|
117 |
+
|
118 |
+
<hr class="featurette-divider">
|
119 |
+
<hr class="featurette-divider">
|
120 |
+
|
121 |
+
<div class="row featurette">
|
122 |
+
<div class="col-md-8">
|
123 |
+
<h2 class="featurette-heading">虫害防治 —— 蚜虫</h2>
|
124 |
+
<p class="lead" style="font-size:16px">
|
125 |
+
玉米蚜虫在玉米孕穗期多密集在剑叶内和叶鞘上为害。蚜虫边吸食玉米汁液,边排泄大量密露,覆盖叶面上的密露影响光合作用,易引起霉菌寄生,被害植株长势衰弱,发育不良,产量下降。玉米蚜虫为害高峰期是在玉米孕穗期,喷药防治比较困难。
|
126 |
+
<br><br>
|
127 |
+
当每10株玉米平均蚜量500头以上时,应进行药剂防治。药剂可选用10%吡虫啉可湿性粉剂1000倍液,或20%康福多浓可溶剂8000倍液,或70%艾美乐水分散剂20000―25000倍液,0.36%绿植苦参碱水剂500倍液,或10%高效氯氰菊酯乳油2000倍液等药剂进行喷雾。
|
128 |
+
</p>
|
129 |
+
</div>
|
130 |
+
<div class="col-md-4" style="background: url('/static/images/corn/蚜虫.jfif') no-repeat center;background-size: cover">
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
|
134 |
+
<hr class="featurette-divider">
|
135 |
+
|
136 |
+
<div class="row featurette">
|
137 |
+
<div class="col-md-8 order-md-2">
|
138 |
+
<h2 class="featurette-heading">虫害防治 —— 红蜘蛛</h2>
|
139 |
+
<p class="lead" style="font-size:16px">
|
140 |
+
玉米红蜘蛛属于螨类,又称火龙、火蜘蛛、红砂等。6月中下旬进入上苗盛期,7、8月份为为害盛期,先在玉米田点片发生,遇适宜的气候条件将迅速蔓延全田。
|
141 |
+
<br><br>
|
142 |
+
药剂防治措施:可选用0.2%阿维虫清乳油2500倍液、15%扫螨净3000倍液、20%扫利乳油2000倍液、1.8%集琦虫螨克乳油3000倍液等药剂喷雾中下部叶片;同时还可采取每亩用1―1.5公斤甲拌磷颗粒剂或甲拌磷乳油拌适量细砂隔行均匀撒于玉米行间。
|
143 |
+
</p>
|
144 |
+
</div>
|
145 |
+
<div class="col-md-4" style="background: url('/static/images/corn/红蜘蛛.jpg') no-repeat center;background-size: cover">
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
</div>
|
149 |
+
</div>
|
150 |
+
</main>
|
151 |
+
<script src="/static/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
|
152 |
+
</body>
|
153 |
+
</html>
|