从安装软件到flask框架搭建可视化大屏(一)——创建一个flask页面,零基础也可以学会
1.第一步:安装软件
Flask是一个轻量级Web应用框架,用python代码编写,简单方便应用。
如何安装pycharm_pycharm只能安装在c盘吗-CSDN博客
Pycharm分为专业版和社区版,是python的主流工具
如何安装Anaconda_如何安装anacoda csdn-CSDN博客
Anaconda是一个python包的集成库,由于python语言编程了大量的集成库,在使用python的过程中,需要安装对应的python第三方库,安装anaconda之后就会非常方便。
安装完上面这两个软件,还要进行配置,进行下面的操作。
如何安装pycharm的包_pycharm本地安装包-CSDN博客
如何给pycharm配置Anaconda环境-CSDN博客
Mysql数据库
在安装mysql数据库和对应的可视化工具Navicat。
如何在window是安装mysql数据库(从零开始)_windows 安装mysql-CSDN博客
mysql(数据库)可视化工具——Navicat Premium-CSDN博客
安装配置之后,就可以开始flask框架的创建和编写。
2.第二部:创建一个flask项目
由于flask的创建需要依赖于第三方库,所以要先安装对应的第三方库,可以参考下面的博客。
如何安装pycharm的包_pycharm本地安装包-CSDN博客
打开终端,安装包的命令
pip install flask
如果还有缺包现象,使用安装命令,安装对应包
pip install 包名
安装完毕之后,(也可以在pychram终端上安装对应包),打开pycharm
如果 对应不同的界面,也不要担心,主要就找到创建项目的对应按钮,只有可以找到都可以。
点击创建项目(New Project)
选择Flask框架,根据自己的需求,选择对应发项目名和创建位置。
点击创建(Create)
会出来加载页面,等待一会即可,如果没有安装对应flask第三方库 是会创建失败的,一定要注意查看报错信息,安装对应发第三方库。
创建完毕之后,页面如下,点击运行
打开网站,出现如下界面,代表你创建成功。
Flask框架目录
根据自己的实际需求建立,有些可能没有。
# 创建基本目录结构:
flask_project/
├── __init__.py
├── app.py
├── templates/
│ ├── index.html
│ ├── about.html
│ └── login.html
├── models/
│ ├── base.py
│ ├── user.py
│ └── db.py
├── security/
│ ├── __init__.py
│ ├── web_saml_authenticator.py
└── flaskr.py # 或者 app.py,视具体实现而定
1.__init__.py:项目元文件。
2.app.py:Flask应用的核心配置和初始化。
3.templates/:存储HTML模板文件。
4.models/:存储数据库模型类。
5.security/:安全策略的定义。
6.flaskr.py:主Flask应用逻辑。
下面是整个项目所需的文件夹,可以一步到位,也可以创建一个写一个。由于本项目已经完成,内很多都是固定格式,这里需要大家自行理解,需要大家根据自己的实际需求进行改善。
3.第三部:编写代码(这里以我的项目为准,我的项目是,利用flask框架搭建可视化平台,带登录界面,登录界面连接到后台mysql数据库。)
这是使用pycharm创建的基本文件夹,这里需要进行一下新的目录的创建
下面是整个项目所需的文件夹,可以一步到位,也可以创建一个写一个。由于本项目已经完成,内很多都是固定格式,这里需要大家自行理解,需要大家根据自己的实际需求进行改善。
3.1首先进行app.py的编写
1.导入模块:
from flask import Flask, render_template, redirect, url_for, flash
from config import Config
from models.models import db, User
from forms.forms import LoginForm, RegisterForm
from views.views import views_bp
Flask:用于创建 Flask 应用。
render_template、redirect、url_for、flash:Flask 模板渲染和路由重定向函数。
Config:配置文件,包含应用的设置信息(如 debug 状态)。
db:Flask 的数据库对象。
User:用户模型类。
LoginForm, RegisterForm:登录和注册形式。
views_bp:包含视图蓝图的模块。
2.创建应用:
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
with app.app_context():
db.create_all()
# 创建默认用户(如果不存在)
if not User.query.filter_by(username='admin').first():
user = User(username='admin', password='password')
db.session.add(user)
db.session.commit()
初始化 Flask 应用,并加载配置文件。
在应用上下文中初始化数据库,创建所有表。
检查是否存在 admin 用户,如果不存在则创建默认用户。
3.注册视图蓝图:
app.register_blueprint(views_bp)
将 views_bp 中的视图函数添加到应用中,使其可用。
4.定义路由:
@app.route('/')
def index():
return redirect(url_for('views.login'))
@app.route('/quota')
def quota():
return render_template('quota.html')
@app.route('/trend')
def trend():
return render_template('trend.html')
@app.route('/chronic')
def chronic():
return render_template('chronic.html')
@app.route('/go_to_quota')
def go_to_quota():
return redirect(url_for('views.quota'))
@app.route('/go_to_trend')
def go_to_trend():
return redirect(url_for('views.trend'))
@app.route('/go_to_chronic')
def go_to_chronic():
return redirect(url_for('views.chronic'))
定义了多个路由:
index:默认路由重定向到登录页面。
quota, trend, chronic:生成相应模板的路由。
go_to_quota, go_to_trend, go_to_chronic:创建重定向到相应视图函数的路由。
5.运行应用:
if __name__ == '__main__':
app.run(debug=True)
检查 __main__ 是否是当前模块,如果是,则启动 Flask 应用,并设置 debug 模式以便调试。
这段代码创建了一个基本的 Flask 应用程序:
初始化 Flask 应用并加载配置。
初始化数据库并创建默认用户。
注册视图蓝图并将路由映射到相应的视图函数。
定义了多个路由,并重定向到不同的视图或模板。
在命令行启动应用,设置 debug 以便调试。
3.2创建config.py文件,编写代码
这段代码包含一个名为 Config 的类,定义了三个静态属性用于配置应用程序的运行环境。此外,还导入了 os 模块,这通常用于访问系统环境变量。
1.导入模块:
import os
这行代码加载了 Python 内置的 os 模块,允许访问操作系统相关的环境变量和文件路径。
2.定义 Config 类:
class Config:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
SQLALCHEMY_DATABASE_URI = 'mysql+mysqlconnector://root:mysql@localhost:3306/demologin'
SQLALCHEMY_TRACK_MODIFICATIONS = False
这部分代码定义了一个嵌套类 Config,包含三个静态属性:
SECRET_KEY:使用 os.environ.get('SECRET_KEY') 获取环境变量中的 SECRET_KEY 值。如果该环境变量不存在,则默认使用 'you-will-never-guess'。
SQLALCHEMY_DATABASE_URI:这是一个字符串,表示应用程序使用的数据库连接信息。这串字符串遵循 SQLAlchemy 的标准格式(diaLECT+driver://username:password@host:port/database),具体指向:mysql 数据库,默认名称为 demologin,连接到 localhost 端口 3306。
SQLALCHEMY_TRACK_MODIFICATIONS:这是一个布尔值,默认设为 False。它指示 SQLAlchemy 是否跟踪数据库修改事件,以便在需要时进行回滚或重置。
3.3创建views文件夹,并在下面创建一个views.py文件,并进行程序编写
1. 导入模块
from flask import Blueprint, render_template, redirect, url_for, flash, request, session
from forms.forms import LoginForm, RegisterForm
from models.models import db, User
Flask 相关模块:
Blueprint:用于将应用模块化,方便组织和管理不同功能的路由。
render_template:用于渲染 HTML 模板。
redirect 和 url_for:redirect 用于重定向到指定的 URL,url_for 用于根据视图函数名生成对应的 URL。
flash:用于在会话中存储一次性消息,通常用于向用户显示提示信息。
request:用于处理 HTTP 请求。
session:用于管理用户会话,存储用户的登录状态等信息。
自定义模块:
LoginForm 和 RegisterForm:从 forms.forms 模块导入,用于处理登录和注册表单。
db 和 User:从 models.models 模块导入,db 是 SQLAlchemy 数据库实例,User 是数据库中的用户模型。
2. 创建蓝图
views_bp = Blueprint('views', __name__)
创建一个名为 views 的蓝图,用于组织和管理视图函数。
3. 登录视图函数
@views_bp.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
user = User.query.filter_by(username=username).first()
# TODO: Implement password hashing
if user and user.password == password:
flash('登录成功!', 'success')
# 设置用户会话
session['username'] = user.username
return redirect(url_for('views.index')) # 登录后跳转到 index.html
else:
flash('无效的用户名或密码', 'danger')
return render_template('login.html', form=form)
路由定义:处理 /login 路径的 GET 和 POST 请求。
表单处理:使用 LoginForm 处理登录表单。当表单提交并验证通过时,从表单中获取用户名和密码。
用户验证:通过用户名查询数据库中的用户,如果用户存在且密码匹配,则登录成功,设置用户会话并跳转到主页;否则,显示错误提示信息。
模板渲染:如果是 GET 请求或表单验证失败,渲染 login.html 模板并传递表单对象。
4. 注册视图函数
@views_bp.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm()
if form.validate_on_submit():
username = form.username.data
password = form.password.data
if User.query.filter_by(username=username).first():
flash('用户名已存在', 'danger')
return redirect(url_for('views.register'))
user = User(username=username, password=password)
db.session.add(user)
try:
db.session.commit()
flash('注册成功,请登录', 'success')
return redirect(url_for('views.login'))
except Exception as e:
db.session.rollback()
flash('注册失败,请重试', 'danger')
print(f"注册错误: {e}")
else:
# 捕捉密码格式验证失败的情况
if form.password.errors:
flash('注册失败,请重新输入密码', 'danger')
return render_template('register.html', form=form)
路由定义:处理 /register 路径的 GET 和 POST 请求。
表单处理:使用 RegisterForm 处理注册表单。当表单提交并验证通过时,从表单中获取用户名和密码。
用户名检查:检查用户名是否已存在,如果存在则显示错误提示信息并重新加载注册页面。
用户创建:如果用户名不存在,则创建新用户并将其添加到数据库中。如果提交成功,则显示成功提示信息并跳转到登录页面;否则,回滚事务并显示错误提示信息。
密码格式验证:如果表单验证失败且密码字段有错误,则显示密码格式错误的提示信息。
模板渲染:如果是 GET 请求或表单验证失败,渲染 register.html 模板并传递表单对象。
5. 可视化仪表盘视图函数
@views_bp.route('/visual_dashboard')
def visual_dashboard():
# 检查用户是否已登录
if 'username' not in session:
flash('请先登录', 'danger')
return redirect(url_for('views.login'))
return render_template('visual_dashboard.html', title='可视化大屏')
路由定义:处理 /visual_dashboard 路径的请求。
登录检查:检查用户是否已登录,如果未登录,则显示错误提示信息并跳转到登录页面。
模板渲染:如果用户已登录,则渲染 visual_dashboard.html 模板并传递页面标题。
6. 主页视图函数
@views_bp.route('/')
def index():
# 检查用户是否已登录
if 'username' not in session:
flash('请先登录', 'danger')
return redirect(url_for('views.login'))
return render_template('index.html')
路由定义:处理根路径 / 的请求。
登录检查:检查用户是否已登录,如果未登录,则显示错误提示信息并跳转到登录页面。
模板渲染:如果用户已登录,则渲染 index.html 模板。
7. 登出视图函数
@views_bp.route('/logout')
def logout():
session.pop('username', None)
flash('已登出', 'success')
return redirect(url_for('views.login'))
路由定义:处理 /logout 路径的请求。
会话处理:从会话中移除用户名,显示登出成功的提示信息,并跳转到登录页面。
8. 其他视图函数
@views_bp.route('/quota')
def quota():
return render_template('quota.html')
@views_bp.route('/trend')
def trend():
return render_template('trend.html')
@views_bp.route('/chronic')
def chronic():
return render_template('chronic.html')
@views_bp.route('/go_to_quota')
def go_to_quota():
return redirect(url_for('views.quota'))
@views_bp.route('/go_to_trend')
def go_to_trend():
return redirect(url_for('views.trend'))
@views_bp.route('/go_to_chronic')
def go_to_chronic():
return redirect(url_for('views.chronic'))
这些视图函数分别处理不同的路由,用于渲染相应的 HTML 模板或重定向到指定的视图函数。
3.4创建forms文件夹,并在下面创建一个forms.py文件,并进行程序编写
这段代码定义了两个基于 Flask-WTF 的表单类,用于处理用户登录和注册的表单数据。以下是对代码的详细分析:
1. 导入模块
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, EqualTo, Regexp
FlaskForm:Flask-WTF 提供的基类,用于创建表单类。
StringField、PasswordField、SubmitField:WTForms 提供的表单字段类型,分别用于处理文本输入、密码输入和提交按钮。
DataRequired、Length、EqualTo、Regexp:WTForms 提供的验证器,用于验证表单字段的数据。
2. 登录表单类 LoginForm
class LoginForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(min=4, max=25)],
render_kw={"placeholder": "请输入用户名"})
password = PasswordField('密码', validators=[DataRequired(), Length(min=6, max=80)],
render_kw={"placeholder": "请输入密码"})
submit = SubmitField('登录')
字段定义:
username:StringField 类型,用于输入用户名。设置了两个验证器:
DataRequired():确保该字段不为空。
Length(min=4, max=25):确保用户名长度在 4 到 25 个字符之间。
render_kw:用于设置 HTML 输入框的属性,这里设置了 placeholder 提示信息。
password:PasswordField 类型,用于输入密码。设置了两个验证器:
DataRequired():确保该字段不为空。
Length(min=6, max=80):确保密码长度在 6 到 80 个字符之间。
同样设置了 placeholder 提示信息。
submit:SubmitField 类型,用于提交表单,按钮文本为 “登录”。
3. 注册表单类 RegisterForm
class RegisterForm(FlaskForm):
username = StringField('用户名', validators=[DataRequired(), Length(min=4, max=25)],
render_kw={"placeholder": "请输入用户名"})
password = PasswordField('密码', validators=[
DataRequired(),
Length(min=6),
Regexp(
'^(?=.*[a-z])(?=.*[A-Z])(?=.*\W).+$',
message='密码至少包含一个大写字母,一个小写字母和一个特殊字符'
)
],
render_kw={"placeholder": "请输入密码"})
confirm = PasswordField('确认密码', validators=[EqualTo('password')],
render_kw={"placeholder": "请再次输入密码"})
submit = SubmitField('确认')
字段定义:
username:与登录表单中的 username 字段类似,确保用户名不为空且长度在 4 到 25 个字符之间,并设置了 placeholder 提示信息。
password:PasswordField 类型,用于输入密码。设置了三个验证器:
DataRequired():确保该字段不为空。
Length(min=6):确保密码长度至少为 6 个字符。
Regexp('^(?=.*[a-z])(?=.*[A-Z])(?=.*\W).+$', message='密码至少包含一个大写字母,一个小写字母和一个特殊字符'):使用正则表达式验证密码,要求密码至少包含一个小写字母、一个大写字母和一个特殊字符。如果不满足条件,会显示自定义的错误信息。
同样设置了 placeholder 提示信息。
confirm:PasswordField 类型,用于确认密码。设置了一个验证器:
EqualTo('password'):确保该字段的值与 password 字段的值相同。
设置了 placeholder 提示信息。
submit:SubmitField 类型,用于提交表单,按钮文本为 “确认”。
3.5创建models文件夹,并在下面创建一个models.py文件,并进行程序编写
1. 导入模块
from flask_sqlalchemy import SQLAlchemy
这里导入了 SQLAlchemy 类,它是 Flask - SQLAlchemy 扩展的核心类,用于在 Flask 应用中集成 SQLAlchemy 库,方便进行数据库操作。
2. 创建数据库实例
db = SQLAlchemy()
创建了一个 SQLAlchemy 的实例 db,这个实例将用于与数据库进行交互,比如定义模型、执行数据库查询等。
3. 定义用户模型类 User
class User(db.Model):
__tablename__ = 'user' # 显式指定表名为 'user'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
password = db.Column(db.String(150), nullable=False)
__tablename__ 属性:显式指定了该模型对应的数据库表名为 user。如果不指定,SQLAlchemy 会根据类名自动生成表名,但显式指定可以让代码的意图更加清晰。
id 字段:使用 db.Column 定义了一个整数类型的列 id,并将其设置为主键(primary_key=True)。主键用于唯一标识表中的每一行记录。
username 字段:定义了一个字符串类型的列 username,最大长度为 150 个字符。unique=True 表示该字段的值在表中必须是唯一的,nullable=False 表示该字段不能为空。
password 字段:同样是字符串类型的列,最大长度为 150 个字符,且不能为空。
4. __repr__ 方法
def __repr__(self):
return f'<User {self.username}>'
__repr__ 方法是 Python 类的一个特殊方法,用于返回对象的字符串表示形式。这里返回一个格式化的字符串,包含了用户的用户名,方便在调试和日志记录时识别对象。
4.第四部分:下面开始前段页面的编写,前端页面使用html+css+js语言编写
login.html,register.html,res.html,base.html这四个页面是登录和注册相关页面;chronic.html,
index.html,NCDindex.html,quota.html,trend.html,这四个是数据可视化大屏
对应页面。
Static文件夹下的文件
这里存储的是对应页面编写的文件格式,包括样式(css)、字体(font)、图片(img)、特效(js)。这里面的内容都可以根据自己的需求进行更改。
4.1base.html
这段代码是一个基于 Flask 模板引擎(如 Jinja2)的 HTML 模板文件,用于构建可视化系统的页面。它定义了页面的基本结构,包括头部信息、主体内容和引入的静态资源,同时使用了模板继承的特性,方便不同页面复用通用的结构和样式。
代码详细分析
1. 文档声明和头部信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}可视化系统{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<!DOCTYPE html>:声明文档类型为 HTML5。
<html lang="en">:指定文档的语言为英语。
<meta charset="UTF-8">:设置文档的字符编码为 UTF - 8,确保能够正确显示各种语言字符。
{% block title %}可视化系统{% endblock %}:这是 Jinja2 模板引擎的 block 标签,用于定义一个名为 title 的块。默认情况下,页面标题为 “可视化系统”,但子模板可以重写这个块来设置不同的标题。
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">:使用 url_for 函数生成静态 CSS 文件 styles.css 的 URL,并将其链接到页面中,用于应用自定义样式。
2. 主体内容
<body>
{% block body %}
<div class="login-background">
<div class="login-container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</div>
<img src="https://sso.xyafu.edu.cn/sso/img/text.png" alt="标语" class="slogan">
<img src="https://www.xyafu.edu.cn/images/logo.png" alt="Logo" class="logo">
</div>
{% endblock %}
{% block body %}:定义了一个名为 body 的块,子模板可以重写这个块来修改页面主体部分的内容。
<div class="login-background"> 和 <div class="login-container">:这两个 div 元素用于构建登录页面的背景和容器,通过 CSS 类名可以对其进行样式设置。
{% with messages = get_flashed_messages(with_categories=true) %}:使用 get_flashed_messages 函数获取 Flask 应用中存储的闪现消息,并将其按类别分组。闪现消息通常用于在页面中显示一次性的提示信息,如登录成功、注册失败等。
{% if messages %} 和 {% for category, message in messages %}:遍历闪现消息列表,如果有消息则显示在页面上。每个消息被包裹在一个 <div class="alert alert-{{ category }}"> 元素中,category 可以是 success、danger 等,用于设置不同的提示样式。
{% block content %}:定义了一个名为 content 的块,子模板可以在这个块中插入具体的页面内容,如登录表单、注册表单等。
<img src="https://sso.xyafu.edu.cn/sso/img/text.png" alt="标语" class="slogan"> 和 <img src="https://www.xyafu.edu.cn/images/logo.png" alt="Logo" class="logo">:插入两个图片元素,分别显示标语和 logo,并通过 CSS 类名进行样式设置。
3. 脚本引入
<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
</body>
</html>
<script src="{{ url_for('static', filename='js/scripts.js') }}">:使用 url_for 函数生成静态 JavaScript 文件 scripts.js 的 URL,并将其引入到页面中,用于实现一些交互功能。
4.2login.html
这段代码是一个基于 Flask 框架和 Jinja2 模板引擎的 HTML 模板文件,它继承自 base.html 模板,用于渲染用户登录页面。代码中展示了如何使用 Flask - WTForms 生成的表单对象来构建 HTML 表单,以及如何通过 Jinja2 模板语法实现页面的动态内容。
代码详细分析
1. 模板继承
html
{% extends "base.html" %}
使用 {% extends %} 标签表明该模板继承自 base.html 模板。这意味着该模板会复用 base.html 中定义的通用结构和样式,如头部信息、页面布局等,同时可以在特定的 block 中插入自己的内容。
2. 内容块重写
{% block content %}
<!-- 具体内容 -->
{% endblock %}
{% block content %} 是 base.html 中定义的一个可重写的块,这里对其进行了重写,插入了登录页面的具体内容。当渲染该模板时,base.html 中 content 块的默认内容会被这里的内容替换。
3. 登录标题
<h2>登录</h2>
显示一个二级标题 “登录”,用于提示用户当前页面的功能。
4. 表单创建
<form method="POST">
{{ form.hidden_tag() }}
<p>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password(size=32) }}
</p>
<p>{{ form.submit() }}</p>
</form>
<form method="POST">:创建一个 HTML 表单,使用 POST 方法提交表单数据。
{{ form.hidden_tag() }}:这是 Flask - WTForms 提供的一个模板函数,用于生成表单的 CSRF(跨站请求伪造)保护字段。CSRF 保护是一种安全机制,用于防止恶意网站通过伪装成合法用户来提交表单数据。
{{ form.username(size=32) }}:渲染表单中的 username 字段,size=32 指定了输入框的宽度为 32 个字符。
{{ form.password(size=32) }}:渲染表单中的 password 字段,同样指定输入框宽度为 32 个字符。
{{ form.submit() }}:渲染表单中的提交按钮。
5. 注册链接
<p>没有账号? <a href="{{ url_for('views.register') }}">注册</a></p>
显示一个提示信息和注册链接。{{ url_for('views.register') }} 是 Jinja2 模板语法,使用 Flask 的 url_for 函数生成 views 蓝图中 register 视图函数对应的 URL。用户点击该链接后,会跳转到注册页面。
4.3res.html
这段 HTML 代码构建了一个用户注册页面,页面中包含一个注册表单,用户可以输入用户名和密码进行注册,同时还有引导已有账号用户去登录的提示信息。
代码详细分析
1. 文档声明和头部信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<!DOCTYPE html>:声明文档类型为 HTML5。
<html lang="en">:指定页面语言为英语,但页面实际包含中文内容,这里的 lang 属性与实际不符,可修改为 lang="zh-CN"。
<meta charset="UTF-8">:设置字符编码为 UTF - 8,确保页面能正确显示各种字符。
<title>Title</title>:页面标题为 “Title”,可修改为更具描述性的标题,如 “用户注册”。
2. 主体内容
容器结构
<div class="cont-parent">
<div class="cont">
.cont-parent 和 .cont 为外层容器,可能用于整体布局和样式控制,但从代码来看,没有具体的样式应用,可结合 CSS 进行样式设计。
注册表单部分
<div class="form sign-in">
<h2>Time to feel like home,</h2>
<form action="/register" method="post">
<label>
<span>用户名</span>
<input type="text" name="username" placeholder="Username" required/>
</label>
<label>
<span>密码</span>
<input type="password" name="password" placeholder="Password" required/>
</label>
<button type="submit" class="submit">注册</button>
</form>
<button type="button" class="fb-btn">Join with <span>facebook</span></button>
</div>
<h2>Time to feel like home,</h2>:标题文案与页面功能关联不大,可修改为更合适的文案,如 “立即注册开启精彩之旅”。
<form action="/register" method="post">:定义一个表单,表单数据将以 POST 方法提交到 /register 路径。
<label> 标签:用于将输入框和对应的提示文本关联起来,增强用户体验。
<input> 标签:
type="text" 和 type="password" 分别用于输入用户名和密码。
name="username" 和 name="password" 为表单字段的名称,服务器端可以通过这些名称获取用户输入的值。
placeholder 属性为输入框提供提示信息。
required 属性表示该字段为必填项。
<button type="submit" class="submit">注册</button>:提交按钮,点击后会提交表单数据。
<button type="button" class="fb-btn">Join with <span>facebook</span></button>:提供了使用 Facebook 账号注册的按钮,但没有添加相应的功能逻辑,可根据实际需求添加。
引导登录部分
<div class="sub-cont">
<div class="img">
<div class="img__text m--up">
<h2>已经有账号了?</h2>
<p>那就去<a href="/">登录</a>吧!</p>
</div>
</div>
</div>
为已有账号的用户提供引导信息,点击 “登录” 链接会跳转到根路径 /。
4.4register.html
这段代码是一个基于 Flask 框架和 Jinja2 模板引擎的 HTML 模板文件,用于渲染用户注册页面。它继承自 base.html 模板,利用 Flask - WTForms 生成的表单对象构建了注册表单,并且提供了引导已有账号用户去登录的链接。
代码详细分析
1. 模板继承
html
{% extends "base.html" %}
通过 {% extends %} 标签,表明该模板继承自 base.html 模板。这意味着它会复用 base.html 中定义的通用页面结构,如头部、页脚、公共样式等,同时可以在特定的 block 区域插入自己的内容。
2. 内容块重写
{% block content %}
<!-- 具体内容 -->
{% endblock %}
{% block content %} 是在 base.html 中预先定义的可重写块。这里对其进行重写,插入了注册页面的具体内容。当该模板被渲染时,base.html 里 content 块的默认内容会被这里的内容替换。
3. 注册标题
<h2>注册</h2>
显示一个二级标题 “注册”,明确告知用户当前页面的功能。
4. 表单创建
<form method="POST">
{{ form.hidden_tag() }}
<p>
{{ form.username(size=32) }}
</p>
<p>
{{ form.password(size=32) }}
</p>
<p>
{{ form.confirm(size=32) }}
</p>
<p>{{ form.submit() }}</p>
</form>
<form method="POST">:创建一个 HTML 表单,使用 POST 方法提交表单数据。
{{ form.hidden_tag() }}:这是 Flask - WTForms 提供的模板函数,用于生成表单的 CSRF(跨站请求伪造)保护字段。CSRF 保护是一种安全机制,可防止恶意网站伪装成合法用户提交表单数据。
{{ form.username(size=32) }}:渲染表单中的 username 字段,size=32 指定输入框的宽度为 32 个字符。
{{ form.password(size=32) }}:渲染表单中的 password 字段,同样设置输入框宽度为 32 个字符。
{{ form.confirm(size=32) }}:渲染表单中的 confirm 字段(确认密码),输入框宽度也为 32 个字符。
{{ form.submit() }}:渲染表单中的提交按钮。
5. 登录引导链接
<p>已有账号? <a href="{{ url_for('views.login') }}">登录</a></p>
显示一个提示信息和登录链接。{{ url_for('views.login') }} 是 Jinja2 模板语法,借助 Flask 的 url_for 函数生成 views 蓝图中 login 视图函数对应的 URL。用户点击该链接后,会跳转到登录页面。
4.5chronic.html
这段代码构建了一个数据可视化的演示页面,页面包含顶部导航栏和内容部分。顶部导航栏提供了不同功能页面的链接,内容部分有一个搜索框和一个展示慢病病人信息的表格,同时具备分页功能。
代码详细分析
1. 文档声明和头部信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据可视化demo</title>
<link href="../static/css/common.css" rel="stylesheet">
<link href="../static/css/bootstrap.min.css" rel="stylesheet">
<link href="../static/css/bootstrap-table.css" rel="stylesheet">
<link href="../static/css/pagination.css" rel="stylesheet">
<script src="../static/js/Plugin/jquery-3.3.1.min.js"></script>
<script src="../static/js/Plugin/echarts.min.js"></script>
<script src="../static/js/Plugin/jquery.pagination.min.js"></script>
<script src="../static/js/common.js"></script>
<script src="../static/js/chronic.js"></script>
</head>
<!DOCTYPE html>:声明文档类型为 HTML5。
<html lang="en">:指定页面语言为英语,但页面中存在中文内容,建议修改为 lang="zh-CN" 以符合实际情况。
<meta charset="UTF-8">:设置字符编码为 UTF - 8,确保页面能正确显示各种字符。
<title>数据可视化demo</title>:设置页面标题为 “数据可视化 demo”。
<link> 标签:引入了多个 CSS 文件,包括自定义的 common.css、Bootstrap 框架的 bootstrap.min.css、bootstrap-table.css 以及分页样式 pagination.css。
<script> 标签:引入了多个 JavaScript 文件,包括 jQuery、ECharts 库、分页插件 jquery.pagination.min.js 以及自定义的 common.js 和 chronic.js。
2. 顶部导航栏
<header class="header left">
<div class="left nav">
<ul>
<li class="nav_active"><i class="nav_1"></i><a href="{{ url_for('index') }}">采集概况</a></li>
<li><i class="nav_2"></i><a href="{{ url_for('quota') }}">指标分析</a></li>
<li><i class="nav_3"></i><a href="{{ url_for('trend') }}">趋势分析</a></li>
<li><i class="nav_4"></i><a href="{{ url_for('chronic') }}">慢病病人列表</a></li>
</ul>
</div>
<div class="header_center left" style="position:relative">
<h2><strong>大数据展示</strong></h2>
</div>
<div class="right nav text_right">
<ul>
</ul>
</div>
</header>
<header> 标签:定义页面的顶部导航栏。
<div class="left nav">:左侧导航栏,包含多个 <li> 列表项,每个列表项中有一个图标 <i> 和一个链接 <a>,链接使用 Flask 的 url_for 函数生成对应的 URL。
<div class="header_center left">:中间部分,显示标题 “大数据展示”。
<div class="right nav text_right">:右侧导航栏,目前为空。
3. 内容部分
<div class="con left" style="width: 98%;margin-left: 1%;margin-bottom: 25px;">
<input type="text" placeholder="请输入姓名身份证" style="width: 180px;height: 28px;border-radius: 3px;text-indent: 1em;border: 1px solid#4b8df8;color: #fff;" /><button class="btn btn-primary btn-sm" style="margin-left:20px"><span class="glyphicon glyphicon-search"></span>查询</button>
<div class="div_any_child">
<div class="table_p" style="height: 96%;margin-top: 20px;">
<table>
<thead><tr>
<th>序号</th>
<th>姓名</th>
<th>慢病</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>萝卜1</td><td>高血压</td><td><button class="btn btn-primary btn-sm">查看</button></td></tr>
<!-- 省略其他行 -->
<tr><td>10</td><td>萝卜0</td><td>糖尿病</td><td><button class="btn btn-primary btn-sm">查看</button></td></tr>
</tbody>
</table>
</div>
<div class="box">
<div id="pagination" class="page fl"></div>
</div>
</div>
</div>
<div class="con left">:内容容器,设置了宽度和边距。
<input> 标签:搜索框,用于输入姓名或身份证信息。
<button> 标签:查询按钮,带有搜索图标。
<table> 标签:展示慢病病人信息的表格,包含表头 <thead> 和表格内容 <tbody>。
<div id="pagination" class="page fl"></div>:分页容器,用于实现表格的分页功能。
4.6index.html
这段 HTML 代码构建了一个数据可视化大屏页面,用于展示医疗相关的数据信息。页面分为顶部导航栏和内容部分,内容部分包含数据总概、统计分析图等板块,使用了 jQuery、ECharts 等库来实现数据可视化,还集成了百度地图 API 展示地图信息。
代码详细分析
1. 文档声明和头部信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据可视化大屏</title>
<link href="../static/css/common.css" rel="stylesheet">
<script src="../static/js/Plugin/jquery-3.3.1.min.js"></script>
<script src="https://www.jq22.com/jquery/echarts-4.2.1.min.js"></script>
<script src="../static/js/Plugin/bmap.min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=5ieMMexWmzB9jivTq6oCRX9j&callback"></script>
<script src="../static/js/common.js"></script>
<script src="../static/js/index.js"></script>
<script src="../static/js/Plugin/laydate/laydate.js"></script>
</head>
文档声明:<!DOCTYPE html> 声明文档类型为 HTML5。
语言设置:<html lang="en"> 指定页面语言为英语,但页面中有大量中文内容,建议改为 lang="zh-CN"。
字符编码:<meta charset="UTF-8"> 设置字符编码为 UTF - 8,确保页面能正确显示各种字符。
标题:<title>数据可视化大屏</title> 设置页面标题。
样式引入:<link href="../static/css/common.css" rel="stylesheet"> 引入自定义的 CSS 样式文件。
脚本引入:
引入 jQuery、ECharts、百度地图相关插件以及自定义的 JavaScript 文件,为页面的交互和可视化功能提供支持。
laydate.js 可能用于日期选择功能。
2. 顶部导航栏
<header class="header left">
<div class="left nav">
<ul>
<li class="nav_active"><i class="nav_1"></i><a href="{{ url_for('index') }}">采集概况</a></li>
<li><i class="nav_2"></i><a href="{{ url_for('quota') }}">指标分析</a></li>
<li><i class="nav_3"></i><a href="{{ url_for('trend') }}">趋势分析</a></li>
<li><i class="nav_4"></i><a href="{{ url_for('chronic') }}">慢病病人列表</a></li>
</ul>
</div>
<div class="header_center left" style="position:relative">
<h2><strong>大数据展示</strong></h2>
</div>
<div class="right nav text_right">
<ul>
</ul>
</div>
</header>
导航栏结构:包含左、中、右三个部分。
左侧导航:提供了四个导航链接,使用 Flask 的 url_for 函数生成对应的 URL,方便用户在不同页面之间切换。
中间标题:显示 “大数据展示”。
右侧导航:目前为空。
3. 内容部分
数据总概
<div class="con_div">
<div class="con_div_text left">
<div class="con_div_text01 left">
<img src="../static/img/info_1.png" class="left text01_img"/>
<div class="left text01_div">
<p>总采集数据量(G)</p>
<p>1235</p>
</div>
</div>
<!-- 其他类似结构省略 -->
</div>
</div>
数据展示:通过图片和文本的组合展示了总采集数据量、当月采集数据量、总门诊数、当月门诊数、总住院数、当月住院数等信息。
统计分析图
<div class="div_any">
<div class="left div_any01">
<div class="div_any_child">
<div class="div_any_title"><img src="../static/img/title_1.png">各医院采集数据量</div>
<p id="pieChart1" class="p_chart"></p>
</div>
<!-- 其他类似结构省略 -->
</div>
<div class="div_any02 left ">
<div class="div_any_child div_height">
<div class="div_any_title any_title_width"><img src="../static/img/title_0.png">信阳市地图 </div>
<div id="mapChart" style="width:97.5%;height:95%;display: inline-block;padding-left: 1.25%;padding-top:2.2%"></div>
</div>
</div>
<div class="right div_any01">
<div class="div_any_child">
<div class="div_any_title"><img src=../static/img/title_3.png">数据采集条数(当日)</div>
<p id="lineChart" class="p_chart"></p>
</div>
<!-- 其他类似结构省略 -->
</div>
</div>
图表容器:使用 <p> 标签作为 ECharts 图表的容器,通过 id 标识不同的图表,如 pieChart1、histogramChart 等。
地图展示:<div id="mapChart"> 用于展示百度地图。
弹窗部分
html
<div id="el-dialog" class="">
<div class="xc_layer"></div>
<div class="popBox" id="printView">
<div class="ttBox"><span class="tt" id="reportTitle">第一医院</span><img src="../static/img/close.png" style="width: 30px;float: right;cursor: pointer;" title="关闭弹窗" class="close"/></div>
<div class="txtBox" id="el-dialog_body">
<!-- 包含更多图表容器 -->
</div>
</div>
</div>
弹窗结构:包含遮罩层和弹窗内容,弹窗中又包含多个图表容器,用于展示更详细的数据信息。
4.7NCDindex.html
这段 HTML 代码构建了一个慢病展示页面,主要用于展示慢病相关的数据信息和统计分析图表。页面结构包含顶部导航栏和内容部分,内容部分又分为数据总概和统计分析图两个板块。使用了 jQuery、ECharts 以及百度地图 API 等技术来实现页面的交互和数据可视化。
代码详细分析
1. 文档声明与头部信息
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>慢病展示</title>
<link href="../static/css/common.css" rel="static/cssheet">
<script src="../static/js/Plugin/jquery-3.3.1.min.js"></script>
<script src="https://www.jq22.com/jquery/echarts-4.2.1.min.js"></script>
<script src="../static/js/Plugin/bmap.min.js"></script>
<script src="http://api.map.baidu.com/api?v=2.0&ak=LelFSt6BfykGf8m3PB5zr8LaXAG2cMg6"></script>
<script src="../static/js/common.js"></script>
<script src="../static/js/NCDindex.js"></script>
</head>
文档类型声明:<!DOCTYPE html> 明确告知浏览器这是一个 HTML5 文档。
语言设置:<html lang="en"> 设定页面语言为英语,但页面内容多为中文,建议修改为 lang="zh-CN" 以符合实际情况。
字符编码:<meta charset="UTF-8"> 确保页面能够正确显示各种字符。
页面标题:<title>慢病展示</title> 为页面设置了标题。
样式引入:<link href="../static/css/common.css" rel="static/cssheet"> 存在错误,rel 属性的值应该为 stylesheet,用于引入自定义的 CSS 样式文件。
脚本引入:
引入 jQuery 库,为后续的 JavaScript 交互提供基础。
引入 ECharts 库,用于绘制各种统计图表。
引入百度地图相关的插件和 API,实现地图展示功能。
引入自定义的 JavaScript 文件 common.js 和 NCDindex.js,可能包含页面的业务逻辑。
2. 顶部导航栏
html
<header class="header left">
<div class="left nav">
<ul>
<li class="nav_active"><i class="nav_1"></i><a href="index.html">慢病概况</a> </li>
<li><i class="nav_2"></i><a href="quota.html">指标分析</a> </li>
<li><i class="nav_3"></i><a href="trend.html">服务预警</a> </li>
</ul>
</div>
<div class="header_center left">
<h2><strong>慢病展示</strong></h2>
</div>
<div class="right nav text_right">
<ul>
</ul>
</div>
</header>
导航栏结构:包含左、中、右三个部分。
左侧导航:提供了三个导航链接,分别指向 index.html、quota.html 和 trend.html,方便用户在不同页面之间切换。
中间标题:显示 “慢病展示”,明确页面主题。
右侧导航:目前为空,可根据需求添加更多导航项。
3. 内容部分
数据总概
html
<div class="con left">
<div class="con_div">
<div class="con_div_text left">
<div class="con_div_text01 left">
<img src="../static/img/info_1.png" class="left text01_img"/>
<div class="left text01_div">
<p>慢病总人次(人)</p>
<p>1235</p>
</div>
</div>
<!-- 其他类似结构省略 -->
</div>
</div>
数据展示:通过图片和文本组合的方式展示了慢病总人次、当月就诊人次、总门诊数、当月门诊数、总住院数、当月住院数等数据信息。
统计分析图
html
<div class="div_any">
<div class="left div_any01">
<div class="div_any_child">
<div class="div_any_title"><img src="../static/img/title_1.png">慢病分布人次</div>
<p id="pieChart" class="p_chart"></p>
</div>
<!-- 其他类似结构省略 -->
</div>
<div class="div_any02 left ">
<div class="div_any_child div_height">
<div class="div_any_title any_title_width"><img src="../static/img/title_0.png">厦门市地图 </div>
<div id="mapChart" style="width:97.5%;height:95%;display: inline-block;padding-left: 1.25%;padding-top:2.2%"></div>
</div>
</div>
<div class="right div_any01">
<div class="div_any_child">
<div class="div_any_title"><img src="../static/img/title_3.png">数据采集条数(当日)</div>
<p id="lineChart" class="p_chart"></p>
</div>
<!-- 其他类似结构省略 -->
</div>
</div>
图表容器:使用 <p> 标签作为 ECharts 图表的容器,通过 id 标识不同的图表,如 pieChart、histogramChart 等。
地图展示:<div id="mapChart"> 用于展示厦门市地图,借助百度地图 API 实现。
4.8quota.html
此 HTML 代码构建了一个数据可视化大屏页面,主要用于展示医疗相关的数据信息和统计分析图表。页面由顶部导航栏和内容部分组成,内容部分包含数据总概和统计分析图两个板块。借助 jQuery、ECharts 等技术实现数据的可视化展示。
代码详细分析
1. 文档声明与头部信息
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据可视化大屏</title>
<link href="../static/css/common.css" rel="stylesheet">
<script src="../static/js/Plugin/jquery-3.3.1.min.js"></script>
<script src="https://www.jq22.com/jquery/echarts-4.2.1.min.js"></script>
<script src="../static/js/Plugin/bmap.min.js"></script>
<script src="../static/js/common.js"></script>
<script src="../static/js/quota.js"></script>
</head>
文档类型声明:<!DOCTYPE html> 明确文档为 HTML5 类型。
语言设置:<html lang="en"> 指定页面语言为英语,但页面存在大量中文内容,建议改为 lang="zh-CN"。
字符编码:<meta charset="UTF-8"> 确保页面能正确显示各种字符。
页面标题:<title>数据可视化大屏</title> 定义了页面的标题。
样式引入:<link href="../static/css/common.css" rel="stylesheet"> 引入自定义的 CSS 样式文件。
脚本引入:
引入 jQuery 库,用于后续的 JavaScript 交互。
引入 ECharts 库,用于绘制统计图表。
引入 bmap.min.js 可能与地图相关,但在页面中未发现地图展示的实际代码。
引入自定义的 JavaScript 文件 common.js 和 quota.js,可能包含页面的业务逻辑。
2. 顶部导航栏
html
<header class="header left">
<div class="left nav">
<ul>
<li class="nav_active"><i class="nav_1"></i><a href="{{ url_for('index') }}">采集概况</a></li>
<li><i class="nav_2"></i><a href="{{ url_for('quota') }}">指标分析</a></li>
<li><i class="nav_3"></i><a href="{{ url_for('trend') }}">趋势分析</a></li>
<li><i class="nav_4"></i><a href="{{ url_for('chronic') }}">慢病病人列表</a></li>
</ul>
</div>>
<div class="header_center left" style="position:relative">
<h2><strong>大数据展示</strong></h2>
</div>
<div class="right nav text_right">
<ul>
</ul>
</div>
</header>
导航栏结构:包含左、中、右三个部分。
左侧导航:提供四个导航链接,使用 Flask 的 url_for 函数生成对应的 URL,方便用户在不同页面间切换。不过存在一个小错误,</div>> 多了一个 > 符号,应改为 </div>。
中间标题:显示 “大数据展示”。
右侧导航:目前为空。
3. 内容部分
数据总概
html
<div class="con left">
<div class="con_div">
<div class="con_div_text left">
<div class="con_div_text01 left">
<img src="../static/img/info_7.png" class="left text01_img"/>
<div class="left text01_div">
<p>全年医疗费用(万元)</p>
<p>1235</p>
</div>
</div>
<!-- 其他类似结构省略 -->
</div>
</div>
数据展示:通过图片和文本结合的方式展示了全年和当月的医疗费用、体检人数,以及西药和中药的占比等数据信息。
统计分析图
html
<div class="div_any">
<div class="left div_any01">
<div class="div_any_child">
<div class="div_any_title"><img src="../static/img/title_5.png">各医院门诊人次(人)</div>
<p id="histogramChart1" class="p_chart"></p>
</div>
<!-- 其他类似结构省略 -->
</div>
</div>
图表容器:使用 <p> 标签作为 ECharts 图表的容器,通过 id 标识不同的图表,如 histogramChart1、lineChart1 等。
4.9trend.html
这段 HTML 代码构建了一个数据可视化大屏页面,聚焦于疾病相关数据的展示与分析。页面包含顶部导航栏和内容部分,内容部分又分为左右两个区域,每个区域都包含多种类型的统计图表和数据表格,用于呈现主要传染病、主要症状、预警信息、主要疾病排行、年龄分布和性别分布等数据。借助 jQuery 和 ECharts 实现交互和可视化效果。
代码详细分析
1. 文档声明与头部信息
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据可视化大屏</title>
<link href="../static/css/common.css" rel="stylesheet">
<script src="../static/js/Plugin/jquery-3.3.1.min.js"></script>
<script src="https://www.jq22.com/jquery/echarts-4.2.1.min.js"></script>
<script src="../static/js/common.js"></script>
<script src="../static/js/trend.js"></script>
</head>
文档类型声明:<!DOCTYPE html> 明确这是 HTML5 文档。
语言设置:<html lang="en"> 设定页面语言为英语,但页面内容多为中文,建议改为 lang="zh-CN"。
字符编码:<meta charset="UTF-8"> 保证页面能正确显示各种字符。
页面标题:<title>数据可视化大屏</title> 确定页面标题。
样式引入:<link href="../static/css/common.css" rel="stylesheet"> 引入自定义 CSS 样式文件。
脚本引入:
引入 jQuery 库,为 JavaScript 交互提供基础。
引入 ECharts 库,用于绘制各种统计图表。
引入自定义 JavaScript 文件 common.js 和 trend.js,可能包含页面业务逻辑。
2. 顶部导航栏
html
<header class="header left">
<div class="left nav">
<ul>
<li class="nav_active"><i class="nav_1"></i><a href="{{ url_for('index') }}">采集概况</a></li>
<li><i class="nav_2"></i><a href="{{ url_for('quota') }}">指标分析</a></li>
<li><i class="nav_3"></i><a href="{{ url_for('trend') }}">趋势分析</a></li>
<li><i class="nav_4"></i><a href="{{ url_for('chronic') }}">慢病病人列表</a></li>
</ul>
</div>
<div class="header_center left" style="position:relative">
<h2><strong>大数据展示</strong></h2>
</div>
<div class="right nav text_right">
<ul>
</ul>
</div>
</header>
导航栏结构:包含左、中、右三个部分。
左侧导航:提供四个导航链接,使用 Flask 的 url_for 函数生成对应 URL,方便用户切换页面。
中间标题:显示 “大数据展示”。
右侧导航:目前为空,可按需添加导航项。
3. 内容部分
页面内容分为左右两个区域,各自包含不同的统计图表和数据表格。
左侧区域
html
<div class="con left" style="width:50%;">
<!-- 多个统计图表和表格 -->
</div>
包含主要传染病的柱状图和折线图,以及病例报告数、死亡数和同比发病数趋势等数据展示。
展示主要症状的柱状图。
显示预警信息的数据表格。
右侧区域
html
<div class="con right" style="width:50%;">
<!-- 多个统计图表 -->
</div>
呈现主要疾病排行的柱状图和折线图。
展示年龄分布和性别分布的饼图。
4.10chronic.js
这段 JavaScript 代码主要使用 ECharts 库创建了多个数据可视化图表,并实现了一个滚动列表效果。具体功能如下:
创建人口增长率与国内生产总值相关的折线图和柱状图:展示全国人口数量、人口老龄化、养老保险等数据随年份的变化。
创建劳动力、消费和投资相关的折线图和柱状图:展示劳动力数量、消费金额和投资比例随年份的变化。
创建城镇与乡村人口、男性与女性人数的饼图:两个饼图每隔 3 秒切换显示。
实现一个滚动列表效果:列表内容可以上下滚动,鼠标悬停时停止滚动,鼠标移开后继续滚动。
实现字体自适应函数:根据浏览器窗口宽度调整字体大小。
代码详细分析
1. 人口增长率与国内生产总值图表
javascript
var lineYear = [2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022];
(function () {
var myChart = echarts.init(document.querySelector(".line .chart"));
// 数据定义
var lineOneData = [3.2, 3.4, 3.5, 3.7, 4.02, 4.19, 4.34, 4.56, 4.80,4.98];
var lineThreeData = [9.7, 10.1, 10.5, 10.8, 11.4, 11.9, 12.6, 13.5, 14.2, 14.9];
var lineTwoData = [136072, 136782, 137462, 138271, 139008, 139538, 140005, 141212, 141260, 141175];
// ECharts 配置项
option = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
// 其他配置项...
series: [
{
name: "养老保险(%)",
type: "line",
yAxisIndex: 1,
// 其他配置项...
data: lineOneData,
},
// 其他系列配置...
],
};
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
})();
数据准备:定义了年份数组 lineYear 和各数据系列数组 lineOneData、lineThreeData、lineTwoData。
图表初始化:使用 echarts.init 方法初始化图表。
配置项设置:设置了图表的工具提示、网格、图例、坐标轴和系列等配置项。
图表渲染:使用 myChart.setOption(option) 渲染图表。
窗口大小自适应:监听 resize 事件,调用 myChart.resize() 方法使图表自适应窗口大小。
2. 劳动力、消费和投资图表
javascript
(function () {
var myChart = echarts.init(document.querySelector(".pie .chart"));
// 数据定义
var barData1 = [12127.3, 7121.2, 327.7, 21127.1, 217.0, 217.5, 5878.1, 548.4,8548.6, 1218.9];
var barData2 = [13220, 14491, 15712, 17111, 18322, 19853, 21559, 21210, 24100, 25124];
var barData3 = [31.2, 31.0, 30.6, 30.1, 29.3, 28.4, 28.2, 30.2, 29.8, 30.2];
// ECharts 配置项
option = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
// 其他配置项...
series: [
{
name: "消费(万元)",
type: "line",
yAxisIndex: 1,
// 其他配置项...
data: barData1,
},
// 其他系列配置...
],
};
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
})();
与第一个图表的实现思路类似,只是数据和系列名称不同。
3. 城镇与乡村人口、男性与女性人数饼图切换
javascript
(function () {
var myChart = echarts.init(document.getElementById('echart5'));
const scatterOption = {
// 城镇与乡村人口饼图配置项
};
const barOption = {
// 男性与女性人数饼图配置项
};
let currentOption = scatterOption;
myChart.setOption(scatterOption);
setInterval(function () {
currentOption = currentOption === scatterOption ? barOption : scatterOption;
myChart.setOption(currentOption, true);
}, 3000);
window.addEventListener("resize", function () {
myChart.resize();
});
})();
图表初始化:初始化饼图。
配置项定义:定义了两个饼图的配置项 scatterOption 和 barOption。
定时切换:使用 setInterval 函数每隔 3 秒切换一次图表配置项。
窗口大小自适应:监听 resize 事件,使图表自适应窗口大小。
4. 滚动列表效果
javascript
(function () {
var speed = 50;
var list = document.getElementById('list');
var list2 = document.getElementById('list2');
var rule = document.getElementById('rule');
list2.innerHTML = list.innerHTML;
function Marquee() {
if (list2.offsetTop - rule.scrollTop <= 0)
rule.scrollTop -= list.offsetHeight;
else {
rule.scrollTop++;
}
}
var MyMar = setInterval(Marquee, speed);
rule.addEventListener('mouseover', function () {
clearInterval(MyMar);
});
rule.addEventListener('mouseout', function () {
MyMar = setInterval(Marquee, speed);
});
})();
元素获取:获取列表元素 list、list2 和滚动容器 rule。
内容复制:将 list 的内容复制到 list2。
滚动函数:定义 Marquee 函数实现滚动效果。
定时滚动:使用 setInterval 函数定时调用 Marquee 函数。
鼠标交互:监听 mouseover 和 mouseout 事件,实现鼠标悬停停止滚动,移开继续滚动的效果。
5. 字体自适应函数
javascript
function transformFontSize(px) {
let clientWidth = window.innerWidth || document.body.clientWidth;
if (!clientWidth) {
return 0;
}
let fontSize = clientWidth / 1920;
return px * fontSize;
}
根据浏览器窗口宽度计算字体大小,实现字体自适应。
4.11trend.js
这段 JavaScript 代码主要使用 ECharts 库在网页上创建了多个数据可视化图表,用于展示传染病和疾病相关的数据信息,具体包括:
主要传染病柱状图:展示不同传染病的发病数量。
主要症状柱状图:展示不同症状对应的人数。
传染病发病趋势折线图:展示传染病发病人数随时间(由 last_year_month() 函数生成的时间序列)的变化趋势。
主要疾病排行柱状图:展示主要疾病的排行及占比情况。
疾病发病趋势折线图:展示疾病发病人数随时间的变化趋势。
年龄分布玫瑰图:展示不同年龄段的发病人数分布。
性别分布饼图:展示男性和女性的发病人数占比。
代码详细分析
1. 变量和初始化
javascript
var symptomName = last_year_month();
$(function(){
init();
})
symptomName:调用 last_year_month() 函数获取一个时间序列,用于折线图的 x 轴数据。
$(function(){}):这是 jQuery 的文档就绪函数,当文档加载完成后调用 init() 函数进行图表的初始化。
2. init() 函数
javascript
function init(){
var myColor = ['#1089E7', '#F57474', '#56D0E3', '#F8B448', '#8B78F6'];
// 以下是各个图表的初始化和配置
// ...
}
myColor:定义了一个颜色数组,用于主要疾病排行柱状图的颜色设置。
3. 主要传染病柱状图
javascript
var histogramChart1 = echarts.init(document.getElementById('histogramChart1'));
histogramChart1.setOption({
// 配置项
color:['#5bc0de'],
grid:{
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
// 其他配置...
series : [
{
name:'主要传染病',
type:'bar',
barWidth : 20,
data:[2210,1085,926,669,634,452,412,312,156],
},
]
})
使用 echarts.init() 初始化图表。
通过 setOption() 方法设置图表的配置项,包括颜色、网格、坐标轴、系列等。
4. 其他图表
后续的主要症状柱状图、传染病发病趋势折线图等图表的初始化和配置方式与主要传染病柱状图类似,只是配置项根据图表类型和需求有所不同。
4.12NCDindex.js
这段 JavaScript 代码使用 ECharts 库创建了多个数据可视化图表,同时结合百度地图 API 展示地图信息,具体功能如下:
地图展示:使用百度地图展示信阳市及其部分医院的地理位置,点击地图上的标记可触发相应操作。
饼图展示:展示不同疾病的采集数据量占比。
折线图展示:展示不同医院在不同时间点的数据采集量或其他相关数据的变化趋势。
柱状图展示:展示不同医院的门诊人数、住院人次和人均费用等数据。
代码详细分析
1. 数据准备与初始化
javascript
var symptomName = last_month_day();
$(function(){
init();
})
symptomName:调用 last_month_day() 函数获取数据,不过在当前代码中未使用该变量,需确认其用途或是否多余。
$(function(){}):这是 jQuery 的文档就绪函数,确保文档加载完成后执行 init() 函数。
2. init() 函数
javascript
function init(){
// 地图图表初始化
var mapChart = echarts.init(document.getElementById('mapChart'));
mapChart.setOption({
// 地图配置项
bmap: {
center: [118.096435,24.485408],
zoom: 12,
roam: true,
},
// 其他配置...
});
// 地图点击事件处理
mapChart.on('click', function (params) {
console.log(params.value[2]);
// 此处注释部分可根据点击的地点更新页面上的相关数据
});
// 获取百度地图实例并添加控件和设置样式
var bmap = mapChart.getModel().getComponent('bmap').getBMap();
bmap.addControl(new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP,BMAP_SATELLITE_MAP ]}));
bmap.setMapStyle({style:'midnight'});
// 饼图初始化
var pieChart = echarts.init(document.getElementById('pieChart'));
pieChart.setOption({
// 饼图配置项
color:["#87cefa","#ff7f50","#32cd32","#da70d6","#FD6C88"],
// 其他配置...
});
// 折线图 1 初始化
var lineChart = echarts.init(document.getElementById('lineChart'));
lineChart.setOption({
// 折线图 1 配置项
color:["#87cefa","#ff7f50","#32cd32","#da70d6",],
// 其他配置...
});
// 柱状图初始化
var histogramChart = echarts.init(document.getElementById('histogramChart'));
histogramChart.setOption({
// 柱状图配置项
color:["#87cefa","#ff7f50","#32cd32","#da70d6",],
// 其他配置...
});
// 折线图 2 初始化
var lineChart2 = echarts.init(document.getElementById('lineChart2'));
lineChart2.setOption({
// 折线图 2 配置项
color:["#87cefa","#ff7f50","#32cd32","#da70d6",],
// 其他配置...
});
}
地图图表:使用 ECharts 的 bmap 组件结合百度地图 API 展示地图,设置了地图的中心点、缩放级别、漫游功能等。点击地图上的标记会在控制台输出标记的名称,还可根据需要更新页面上的相关数据。
饼图:展示不同疾病的采集数据量占比,设置了颜色、图例、提示框等配置项。
折线图:展示不同医院在不同时间点的数据变化趋势,设置了颜色、图例、坐标轴等配置项。
柱状图:展示不同医院的门诊人数、住院人次和人均费用等数据,设置了颜色、图例、坐标轴、系列等配置项。
4.13quota.js
这段 JavaScript 代码借助 ECharts 库,在网页中创建了多个数据可视化图表,用于展示信阳市几家医院的多项医疗相关数据,具体涵盖:
各医院门诊人次和住院人次柱状图:呈现不同医院的门诊和住院人次占比情况。
手术工作量和床位数量分布玫瑰图:展示各医院的手术工作量和床位数量分布。
医疗费用和体检人次折线图:展示各医院一周内的医疗费用和体检人次变化趋势。
药占比和平均住院天数柱状图:展示各医院的药占比和平均住院天数。
代码详细分析
1. 文档就绪与初始化
javascript
$(function(){
init();
})
运用 jQuery 的文档就绪函数,确保文档加载完毕后执行 init() 函数,以此初始化所有图表。
2. init() 函数
javascript
function init(){
var myColor = ['#1089E7', '#F57474', '#56D0E3', '#F8B448', '#8B78F6'];
// 以下是各图表的初始化与配置
// ...
}
myColor:定义颜色数组,用于柱状图的颜色设置。
3. 各图表初始化与配置
各医院门诊人次柱状图(histogramChart1)
javascript
var histogramChart1 = echarts.init(document.getElementById('histogramChart1'));
histogramChart1.setOption({
// 网格、坐标轴、系列等配置
grid: {
top: '20%',
left: '32%'
},
xAxis: {
show: false
},
yAxis: [
{
// 医院名称配置
},
{
// 对应数值配置
}
],
series: [
{
name: '条',
type: 'bar',
// 数据与样式配置
},
{
name: '框',
type: 'bar',
// 数据与样式配置
}
]
})
通过 echarts.init() 初始化图表,再使用 setOption() 方法设置图表的各种配置项,包含网格、坐标轴、系列等。
各医院住院人次柱状图(histogramChart2)
配置方式与门诊人次柱状图类似,只是数据不同。
手术工作量玫瑰图(pieChart1)
javascript
var pieChart1 = echarts.init(document.getElementById('pieChart1'));
pieChart1.setOption({
color:["#87cefa","#ff7f50","#32cd32","#da70d6",],
tooltip: {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}台"
},
series: [
{
name: '手术工作量',
type: 'pie',
radius: [30, 110],
roseType: 'area',
data: [
{value: 10, name: '信阳第一医院'},
// 其他医院数据
]
}
]
})
设置了颜色、提示框格式、系列类型(玫瑰图)和数据。
医疗费用折线图(lineChart1)
javascript
var lineChart1 = echarts.init(document.getElementById('lineChart1'));
lineChart1.setOption({
color:["#87cefa","#ff7f50","#32cd32","#da70d6",],
tooltip: {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}元"
},
legend: {
data: ['信阳第一医院', '信阳中山医院', '信阳中医院', '信阳第五医院'],
y: 'bottom',
x: 'center',
textStyle: {
color: '#fff',
fontSize: 12
}
},
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
// 坐标轴样式配置
},
yAxis: {
type: 'value',
// 坐标轴样式配置
},
series: [
{
name: '信阳第一医院',
type: 'line',
smooth: true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data: [10, 12, 21, 54, 260, 830, 710]
},
// 其他医院数据
]
})
设置了颜色、提示框格式、图例、坐标轴和系列数据。
体检人次折线图(lineChart2)
配置方式与医疗费用折线图类似,只是数据不同。
床位数量分布玫瑰图(pieChart2)
配置方式与手术工作量玫瑰图类似,只是数据不同。
药占比柱状图(histogramChart3)
javascript
var histogramChart3 = echarts.init(document.getElementById('histogramChart3'));
histogramChart3.setOption({
color: ['#87cefa'],
grid: {
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
tooltip: {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}%"
},
xAxis: {
type: 'category',
data: ['信阳第一医院', '信阳中山医院', '信阳中医院', '信阳第五医院'],
// 坐标轴样式配置
},
yAxis: {
type: 'value',
// 坐标轴样式配置
},
series: [
{
name: '药占比',
type: 'bar',
barWidth: 30,
data: [60, 80, 70, 50]
}
]
})
设置了颜色、网格、提示框格式、坐标轴和系列数据。
平均住院天数柱状图(histogramChart4)
配置方式与药占比柱状图类似,只是数据不同。
4.14index.js
这段 JavaScript 代码结合了 jQuery、ECharts 和 laydate 插件,实现了一个医疗数据可视化页面,主要功能包括:
地图展示:使用 ECharts 的百度地图组件展示信阳市及其部分医院的地理位置,点击地图上的标记会弹出对话框显示相关信息。
多类型图表展示:通过 ECharts 创建多种类型的图表,如饼图、折线图、柱状图等,用于展示医院的采集数据量、门诊和住院人次、医疗费用等数据。
日期选择器:使用 laydate 插件实现日期选择功能。
对话框交互:点击地图标记弹出对话框,点击关闭按钮隐藏对话框。
代码详细分析
1. 全局变量和初始化
javascript
var symptomName = last_month_day();
$(function(){
init();
init2();
$("#el-dialog").addClass("hide");
$(".close").click(function(event) {
$("#el-dialog").addClass("hide");
});
var date = new Date();
var numble = date.getDate();
var today = getFormatMonth(new Date());
$("#date1").html(today);
$("#date2").html(today);
$("#date3").html(today);
$("#date4").html(today);
lay('.demo-input').each(function(){
laydate.render({
type: 'month',
elem: this,
trigger: 'click',
theme: '#95d7fb',
calendar: true,
showBottom: true,
done: function () {
console.log( $("#startDate").val())
}
})
});
});
symptomName:调用 last_month_day() 函数获取一个日期数组,用于部分折线图的 x 轴数据,但该函数未在提供的代码中定义。
$(function(){}):jQuery 的文档就绪函数,确保页面加载完成后执行代码。
init() 和 init2():分别初始化不同组的图表。
$("#el-dialog").addClass("hide"):初始时隐藏对话框。
$(".close").click():为关闭按钮绑定点击事件,点击时隐藏对话框。
laydate.render():使用 laydate 插件为指定的输入框渲染日期选择器。
2. init() 函数
该函数初始化了多个图表,包括地图、饼图、折线图和柱状图:
地图(mapChart):使用 ECharts 的百度地图组件展示信阳市及其部分医院的地理位置,点击地图上的标记会弹出对话框并显示标记名称。
饼图(pieChart1):展示几家医院的采集数据量占比。
折线图(lineChart 和 lineChart2):分别展示不同时间段内几家医院的数据变化趋势。
柱状图(histogramChart):展示几家医院的门诊人数、住院人次和人均费用。
3. init2() 函数
该函数初始化了另外几个图表,包括折线图和饼图:
折线图(lineChart3 和 lineChart4):展示门诊费用、住院费用和医疗费用随日期的变化趋势,同时添加了数据缩放功能。
饼图(pieChart2 和 pieChart3):分别展示发病人数的年龄分布和医疗费用的组成。
代码存在的问题及改进建议
1. 函数依赖问题
问题:last_month_day() 和 getFormatMonth() 函数未在提供的代码中定义,需要确保这些函数存在并能正确返回所需数据。
建议:添加这两个函数的实现,或者从其他文件引入这些函数。
2. 代码复用性问题
问题:多个图表的配置项存在大量重复,如颜色、坐标轴样式、提示框格式等。
建议:将重复的配置项提取成变量或函数,提高代码复用性。例如:
javascript
var commonColors = ["#87cefa","#ff7f50","#32cd32","#da70d6"];
var commonTooltip = {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}"
};
var commonYAxis = {
type: 'value',
axisLine : {onZero: false},
axisLine:{
lineStyle:{
color: '#034c6a'
}
},
axisLabel: {
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
}
},
splitLine:{
lineStyle:{
width:0,
type:'solid'
}
}
};
// 在图表配置中使用
var lineChart = echarts.init(document.getElementById('lineChart'));
lineChart.setOption({
color: commonColors,
tooltip: commonTooltip,
yAxis: commonYAxis,
// 其他配置...
});
3. 数据动态化问题
问题:图表的数据是硬编码的,无法根据实际情况动态更新。
建议:通过 AJAX 请求从后端获取数据,然后将数据填充到图表的配置项中。例如:
javascript
$.ajax({
url: '/get_collected_data',
method: 'GET',
success: function(data) {
var pieChart1 = echarts.init(document.getElementById('pieChart1'));
pieChart1.setOption({
series: [
{
name: '采集数据量',
type: 'pie',
data: data
}
]
});
},
error: function() {
console.error('获取采集数据量失败');
}
});
4. 异常处理问题
问题:在初始化图表时,没有对可能出现的异常进行处理。
建议:添加异常处理代码,例如:
javascript
var mapChart = echarts.init(document.getElementById('mapChart'));
if (!mapChart) {
console.error('地图图表初始化失败');
return;
}
5. 注释和可读性问题
问题:代码中注释较少,尤其是一些复杂的配置项和逻辑,不利于理解和维护。
建议:添加更多详细的注释,解释每个配置项的作用和每个图表的功能。
6. 代码结构问题
问题:init() 和 init2() 函数包含了大量的图表初始化代码,函数过长,不利于维护。
建议:将每个图表的初始化代码封装成独立的函数,提高代码的可维护性。例如:
javascript
function initMapChart() {
var mapChart = echarts.init(document.getElementById('mapChart'));
mapChart.setOption({
// 地图配置项
});
mapChart.on('click', function (params) {
$("#el-dialog").removeClass('hide');
$("#reportTitle").html(params.value[2]);
});
var bmap = mapChart.getModel().getComponent('bmap').getBMap();
bmap.addControl(new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP,BMAP_SATELLITE_MAP ]}));
bmap.setMapStyle({style:'midnight'});
}
function init() {
initMapChart();
// 初始化其他图表
}
4.15common.js
这段 JavaScript 代码定义了一系列工具函数,用于实现前端页面的多种功能,涵盖网络请求、提示信息展示、加载动画控制、导航栏处理、日期计算以及分页等功能,以下是详细的功能介绍:
详细功能及代码分析
1. 网络请求函数 callResourceAdapter
javascript
function callResourceAdapter(type, url, requestContent, successCallback, failCallback) {
if (requestContent == null){
requestContent = {};
}
if (type == null){
type = 'POST';
}
function invocationSuccess(result) {
var resultJson = result;
if(resultJson.msgCode == '800'){
if (successCallback && typeof(successCallback) == "function") {
successCallback(resultJson.rows,resultJson.map,resultJson.vo,resultJson.msg);
}
}
if(resultJson.msgCode == '801'){
showToast(resultJson.msg);
}
if(resultJson.msgCode == '900'){
var message = '系统错误,请联系管理员';
if(resultJson.msg){
message = resultJson.msg;
}
showToast(message);
if (failCallback && typeof(failCallback) == "function") {
failCallback();
}
}
}
function invocationFailure(error) {
showToast('无法连接至服务器,请稍后再试');
if (failCallback && typeof(failCallback) == "function") {
failCallback();
}
}
$.ajax({
type: type,
url: serverUrl+url,
data: JSON.stringify(requestContent),
crossDomain:true,
contentType: "application/json; charset=utf-8",
timeout:120000,
statusCode:{
404: function() {
showToast('服务器无响应,请稍后再试')
},
422: function() {
showToast('应用程序请求对象错误,请稍后再试')
},
403: function() {
showToast('无访问权限')
},
400: function() {
showToast('应用程序请求无效,请稍后再试')
},
},
success: function (data, textStatus, jqXHR) {
switch (jqXHR.status) {
case 200:
invocationSuccess(data);
break;
default:
break;
}
},
error: function (jqXHR, textStatus,errorThrown) {
invocationFailure(jqXHR);
}
})
}
功能:封装了一个通用的 AJAX 请求函数,可根据传入的请求类型、URL、请求内容进行网络请求,并根据响应状态码和自定义的消息码进行不同的处理。
参数:
type:请求类型,默认为 POST。
url:请求的 URL。
requestContent:请求内容,默认为空对象。
successCallback:请求成功且消息码为 800 时调用的回调函数。
failCallback:请求失败或消息码为 900 时调用的回调函数。
2. 提示信息展示函数
javascript
function showToast(text,timeout) {
$(".yui-toast-mask").remove();
var html = [
'<div class="yui-toast-mask">',
'<div class="yui-toast">',
'<div class="yui-toast-text">'+text+'</div>',
'</div>',
'</div>',
];
var dom = $(html.join(''));
$("body").append(dom);
if(timeout&&typeof(timeout)=='number'){
setTimeout(function () {
dom.remove();
},timeout);
}
$(".yui-toast-mask").click(function () {
dom.remove();
});
}
function hideToast() {
$(".yui-toast-mask").remove();
}
showToast 函数:在页面上显示提示信息,可设置显示时长,点击提示框可手动关闭。
hideToast 函数:隐藏当前显示的提示信息。
3. 加载动画控制函数
javascript
function loaderShow() {
var loadPage = $('<div class="loading" style="top:30%;left:50%;position: absolute;background: transparent;text-align: center;">' +
'<img src="../images/loading.gif" />' +
'</div>');
$("#content").append(loadPage);
}
function loaderHide() {
$(".loading").remove();
}
loaderShow 函数:在 #content 元素中显示加载动画。
loaderHide 函数:隐藏加载动画。
4. 导航栏相关函数
javascript
function getLocationDom() {
var that = this;
var html = "<div id='breadcrumb'>";
$.each(LOCATION,function(index,data){
if(index==0){
html += '<a href="javascript:void(0)" class="tip-bottom"><i class="fa fa-home"></i>'+data+'</a>';
return ;
}
if(index==LOCATION.length-1){
html += '<a class="current">'+data+'</a>';
return ;
}
html += "<a href='javascript:void(0)'>"+data+"</a>";
});
html += "</div>";
$("#content-header").html(html);
}
function getNav(successCallback) {
var postNav = [];
postNav.push('<li class="submenu" data-for= "home">','<a href="javascript:void(0)"><span>首页</span></a>');
postNav.push('<li class="submenu" data-for= "analysis">','<a href="javascript:void(0)"><span>指标统计</span></a>');
postNav.push('<li class="submenu" data-for= "trend">','<a href="javascript:void(0)"><span>趋势排名</span></a>');
$("#sidebar ul").html(postNav.join(''));
if (successCallback&&typeof(successCallback) == 'function'){
successCallback();
}
}
function bindNav(navId) {
var HEIGHT = $("body").height()-100;
$("#content").height(HEIGHT);
$(".container-fluid").slimScroll({
height: HEIGHT+'px', //容器高度,默认250px
size: '5px', //滚动条宽度,默认7px
railColor: '#000000', //滚动条背景轨迹颜色,默认#333333
railOpacity: 0.3, //滚动条背景轨迹透明度,默认0.2
wheelStep: 10, //滚动条滚动值,默认20
disableFadeOut: false //是否禁用鼠标在内容处一定时间不动隐藏滚动条,当设置alwaysVisible为true时该参数无效,默认false
});
$("#"+navId).delegate("li[data-for='home']","click",function(){
window.location.href="home.html"
}).delegate("li[data-for='analysis']","click",function(){
window.location.href="analysis.html"
}).delegate("li[data-for='trend']","click",function(){
window.location.href="trend.html"
})
}
getLocationDom 函数:根据 LOCATION 数组生成面包屑导航,并插入到 #content-header 元素中。
getNav 函数:生成导航栏 HTML 代码并插入到 #sidebar ul 元素中,可传入成功回调函数。
bindNav 函数:为导航栏绑定点击事件,点击不同的导航项会跳转到相应的页面,同时设置内容区域的高度和滚动条样式。
5. 日期计算函数
javascript
function last_year_month() {
var list = [];
var date = getFormatDate(new Date());
var year = date.split("-")[0];
var mouth = date.split("-")[1];
for (var i=0;i<12;i++){
var objM = mouth-i;
var objY = year;
if(objM<=0){
objM = objM+12;
objY = year -1;
}
if(objM<10){
objM = "0"+objM;
}
var obj = objY +"-"+objM;
list.push(obj)
}
return list;
}
function getFormatDate(date){
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
if(month<10){
month = '0'+month.toString();
}
month = month.toString();
if(day<10){
day = '0'+day.toString();
}
day = day.toString();
return year+'-'+month+'-'+day;
}
function last_month_day() {
var list = [];
var date = getFormatDate(new Date());
var year = date.split("-")[0];
var mouth = date.split("-")[1];
var day = date.split("-")[2]-1;
for (var i=0;i<30;i++){
var objM = mouth;
var objD = day-i;
if(objD<=0){
objD = objD+30;
objM = mouth -1;
objM = "0"+objM
}
var obj = year+"-"+objM +"-"+objD;
list.push(obj)
}
return list;
}
function getFormatMonth(date){
var year = date.getFullYear();
var month = date.getMonth()+1;
var day = date.getDate();
if(month<10){
month = '0'+month.toString();
}
month = month.toString();
if(day<10){
day = '0'+day.toString();
}
day = day.toString();
return year+'-'+month;
}
last_year_month 函数:返回过去 12 个月的年月数组。
getFormatDate 函数:将日期对象格式化为 YYYY-MM-DD 格式的字符串。
last_month_day 函数:返回过去 30 天的日期数组。
getFormatMonth 函数:将日期对象格式化为 YYYY-MM 格式的字符串。
6. 分页函数
javascript
function paging(totalPage,currentPage) {
$("#pagination").pagination({
currentPage: currentPage,
totalPage: totalPage,
isShow: true,
count: 8,
homePageText: "首页",
endPageText: "尾页",
prevPageText: "上一页",
nextPageText: "下一页",
callback: function(current) {
$("#current").text(current)
}
});
}
功能:初始化分页插件,可设置总页数、当前页数等参数,并在页码切换时更新当前页码显示。
代码存在的问题及改进建议
1. 变量未定义问题
问题:代码中使用了 serverUrl 和 LOCATION 变量,但未在提供的代码中定义。
建议:确保在使用这些变量之前进行定义,或者将其作为参数传递给相应的函数。
2. 代码复用性问题
问题:getFormatDate 和 getFormatMonth 函数中存在重复的日期格式化代码。
建议:提取重复的代码到一个通用的日期格式化函数中,提高代码复用性。例如:
javascript
function formatDate(date, format) {
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
if (month < 10) {
month = '0' + month.toString();
}
if (day < 10) {
day = '0' + day.toString();
}
if (format === 'YYYY-MM-DD') {
return year + '-' + month + '-' + day;
} else if (format === 'YYYY-MM') {
return year + '-' + month;
}
return '';
}
function getFormatDate(date) {
return formatDate(date, 'YYYY-MM-DD');
}
function getFormatMonth(date) {
return formatDate(date, 'YYYY-MM');
}
3. 错误处理和日志记录
问题:在 callResourceAdapter 函数中,虽然对不同的状态码和消息码进行了处理,但缺乏详细的日志记录,不利于调试和问题排查。
建议:在关键位置添加日志记录,例如在 invocationSuccess 和 invocationFailure 函数中记录相关信息。例如:
javascript
function invocationSuccess(result) {
console.log('请求成功,消息码:', result.msgCode);
var resultJson = result;
if(resultJson.msgCode == '800'){
if (successCallback && typeof(successCallback) == "function") {
successCallback(resultJson.rows,resultJson.map,resultJson.vo,resultJson.msg);
}
}
// 其他处理...
}
function invocationFailure(error) {
console.error('请求失败:', error);
showToast('无法连接至服务器,请稍后再试');
if (failCallback && typeof(failCallback) == "function") {
failCallback();
}
}
4. 兼容性问题
问题:last_month_day 函数中简单地将日期减去 30 天,没有考虑月份天数的差异,可能会导致日期计算错误。
建议:使用 Date 对象的方法进行日期计算,避免手动计算带来的问题。例如:
javascript
function last_month_day() {
var list = [];
var today = new Date();
for (var i = 0; i < 30; i++) {
var date = new Date(today.getTime() - i * 24 * 60 * 60 * 1000);
list.push(getFormatDate(date));
}
return list.reverse();
}
4.16flexible.js
这段 JavaScript 代码是一个立即执行函数,主要用于实现移动端页面的自适应布局,通过设置 rem 单位和检测设备对 0.5px 边框的支持,来优化页面在不同设备上的显示效果。以下是详细的功能分析:
详细功能及代码分析
1. 初始化变量
javascript
var docEl = document.documentElement;
var dpr = window.devicePixelRatio || 1;
docEl:获取文档的根元素(<html> 标签),后续用于设置 rem 单位和添加类名。
dpr:获取设备的像素比,如果设备不支持 window.devicePixelRatio,则默认像素比为 1。
2. 设置页面主体字体大小
javascript
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + "px";
} else {
document.addEventListener("DOMContentLoaded", setBodyFontSize);
}
}
setBodyFontSize();
setBodyFontSize 函数:根据设备像素比设置页面主体(<body> 标签)的字体大小。如果 document.body 已经存在,则直接设置字体大小;如果不存在,则监听 DOMContentLoaded 事件,在页面的 DOM 结构加载完成后再设置字体大小。
3. 设置 rem 单位
javascript
function setRemUnit() {
var rem = docEl.clientWidth / 24;
docEl.style.fontSize = rem + "px";
}
setRemUnit();
setRemUnit 函数:将页面根元素的字体大小设置为页面视口宽度的 1/24,即 1rem 等于页面视口宽度的 1/24。这样在页面布局中使用 rem 单位时,元素的尺寸会根据页面宽度自适应调整。
调用 setRemUnit 函数进行初始设置。
4. 监听窗口变化事件
javascript
window.addEventListener("resize", setRemUnit);
window.addEventListener("pageshow", function(e) {
if (e.persisted) {
setRemUnit();
}
});
监听 resize 事件:当窗口大小发生变化时,调用 setRemUnit 函数重新设置 rem 单位,以保证页面布局的自适应。
监听 pageshow 事件:当页面从缓存中重新显示时,如果 e.persisted 为 true,说明页面是从缓存中恢复的,此时调用 setRemUnit 函数重新设置 rem 单位。
5. 检测设备对 0.5px 边框的支持
javascript
if (dpr >= 2) {
var fakeBody = document.createElement("body");
var testElement = document.createElement("div");
testElement.style.border = ".5px solid transparent";
fakeBody.appendChild(testElement);
docEl.appendChild(fakeBody);
if (testElement.offsetHeight === 1) {
docEl.classList.add("hairlines");
}
docEl.removeChild(fakeBody);
}
当设备像素比 dpr 大于等于 2 时,创建一个临时的 <body> 元素 fakeBody 和一个 <div> 元素 testElement,并为 testElement 设置 0.5px 的透明边框。
将 testElement 添加到 fakeBody 中,再将 fakeBody 添加到文档根元素中。
通过检查 testElement 的 offsetHeight 是否为 1 来判断设备是否支持 0.5px 边框。如果支持,则为文档根元素添加 hairlines 类名,开发者可以在 CSS 中针对该类名设置更细的边框样式。
最后移除临时的 fakeBody 元素。
代码存在的问题及改进建议
1. 代码可配置性
问题:rem 的计算方式是固定的(docEl.clientWidth / 24),缺乏可配置性,不同项目可能需要不同的计算方式。
建议:将 rem 的计算方式作为参数传入立即执行函数,提高代码的灵活性。例如:
javascript
(function flexible(window, document, remDivider = 24) {
// ...
function setRemUnit() {
var rem = docEl.clientWidth / remDivider;
docEl.style.fontSize = rem + "px";
}
// ...
})(window, document, 10); // 可以传入不同的 remDivider 值
2. 兼容性考虑
问题:虽然代码考虑了设备像素比和 0.5px 边框的支持,但对于一些老旧设备可能存在兼容性问题。
建议:可以添加更多的兼容性处理,例如使用媒体查询或 JavaScript 检测来为不同设备提供不同的布局方案。
3. 代码注释和文档
问题:代码中注释较少,对于不熟悉该代码的开发者来说,理解代码的功能和实现细节可能会有困难。
建议:添加更多详细的注释,解释每个函数的作用、参数和返回值,以及关键代码的意图。
4. 事件监听的移除
问题:代码中添加了 resize 和 pageshow 事件监听,但没有提供移除这些事件监听的机制,可能会导致内存泄漏。
建议:可以在适当的时候移除这些事件监听,例如在页面卸载时。可以添加一个 destroy 函数来处理事件监听的移除:
javascript
(function flexible(window, document, remDivider = 24) {
// ...
function setRemUnit() {
var rem = docEl.clientWidth / remDivider;
docEl.style.fontSize = rem + "px";
}
function destroy() {
window.removeEventListener("resize", setRemUnit);
window.removeEventListener("pageshow", pageshowHandler);
}
var pageshowHandler = function(e) {
if (e.persisted) {
setRemUnit();
}
};
setRemUnit();
window.addEventListener("resize", setRemUnit);
window.addEventListener("pageshow", pageshowHandler);
// 可以在需要的时候调用 destroy 函数
// destroy();
// ...
})(window, document, 24);
4.17myMap.js
这段代码使用 ECharts 库绘制了一个中国地图,地图上展示了不同城市之间的人口流动情况,包括流动的总人数、男性人数和女性人数。具体功能如下:
数据准备:定义了中国各个省份和直辖市的经纬度坐标(geoCoordMap)以及城市之间的人口流动数据(MapData)。
数据转换:通过 convertData 函数将原始的人口流动数据转换为 ECharts 所需的格式。
系列数据生成:遍历 MapData 数组,为每个数据项生成三种不同类型的系列(lines 和 effectScatter),用于展示流动路线、动态箭头和起点城市标记。
配置选项设置:设置了地图的基本样式、提示框格式和系列数据。
图表渲染与响应式处理:初始化 ECharts 实例,设置配置选项,并监听窗口大小变化事件,实现图表的自适应调整。
代码详细分析
1. 初始化 ECharts 实例
javascript
var myChart = echarts.init(document.querySelector(".map .chart"));
使用 echarts.init 方法初始化一个 ECharts 实例,绑定到类名为 .map .chart 的 DOM 元素上。
2. 数据定义
javascript
var geoCoordMap = {
// 各个省份和直辖市的经纬度坐标
};
var MapData = [
// 城市之间的人口流动数据,包含起点城市、终点城市、总人数、男性人数和女性人数
];
geoCoordMap 存储了中国各个省份和直辖市的经纬度坐标,用于在地图上定位。MapData 存储了城市之间的人口流动数据。
3. 数据转换函数
javascript
var convertData = function (data) {
var fromCoord = geoCoordMap[data[0].name];
var toCoord = geoCoordMap[data[1].name];
return [
{
fromName: data[0].name,
toName: data[1].name,
coords: [fromCoord, toCoord],
value: data[1].value,
value1: data[1].value1,
value2: data[1].value2,
}
];
};
convertData 函数将原始的人口流动数据转换为包含起点城市、终点城市、经纬度坐标和相关数值的对象数组。
4. 系列数据生成
javascript
var series = [];
MapData.forEach(function (item, i) {
series.push(
{
// 第一个系列:线条效果
},
{
// 第二个系列:动态箭头效果
},
{
// 第三个系列:起点城市标记
}
);
});
遍历 MapData 数组,为每个数据项生成三种不同类型的系列:
第一个系列:使用 lines 类型,展示流动路线的线条效果。
第二个系列:使用 lines 类型,展示动态箭头效果。
第三个系列:使用 effectScatter 类型,展示起点城市的标记。
5. 配置选项设置
javascript
var option = {
tooltip: {
// 提示框配置,根据系列类型显示不同的信息
},
geo: {
// 地图配置,包括地图类型、标签、漫游、缩放和样式
},
series: series
};
设置了地图的提示框格式、地图样式和系列数据。
6. 图表渲染与响应式处理
javascript
myChart.setOption(option);
window.addEventListener("resize", function () {
myChart.resize();
});
使用 setOption 方法将配置选项应用到 ECharts 实例上,渲染图表。监听窗口大小变化事件,当窗口大小改变时,调用 resize 方法重新调整图表大小。
scripts.js
document.addEventListener('DOMContentLoaded', function() {
// 获取 Flash 消息的容器
var flashMessages = document.getElementById('flash-messages');
// 检查 Flash 消息是否存在
if (flashMessages) {
// 设置一个 3 秒后执行的定时器
setTimeout(function() {
// 隐藏 Flash 消息
flashMessages.style.display = 'none';
}, 3000); // 3000 毫秒 = 3 秒
}
});
trend.js
var symptomName = last_year_month();
$(function(){
init();
})
function init(){
var myColor = ['#1089E7', '#F57474', '#56D0E3', '#F8B448', '#8B78F6'];
//主要传染病
var histogramChart1 = echarts.init(document.getElementById('histogramChart1'));
histogramChart1.setOption({
color:['#5bc0de'],
grid:{
left: '5%',
right: '5%',
bottom: '5%',
containLabel: true
},
tooltip : {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}人"
},
calculable : true,
xAxis : [
{
type : 'category',
data : ['感染性腹泻','流行性感冒','登革热','手足口病','水痘','流行性眼腺炎','猩红热','甲型病毒性肝炎','疟疾'],
axisLine:{
lineStyle:{
color: '#5bc0de'
},
},
axisLabel : {
interval:0,
rotate:40,
textStyle: {
color: '#fff'
}
}
}
],
yAxis : [
{
type : 'value',
axisLine:{
lineStyle:{
color: '#5bc0de'
},
},
splitLine: {
"show": false
},
axisLabel: {
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
},
},
}
],
series : [
{
name:'主要传染病',
type:'bar',
barWidth : 20,
data:[2210,1085,926,669,634,452,412,312,156],
},
]
})
//主要症状
var histogramChart2 = echarts.init(document.getElementById('histogramChart2'));
histogramChart2.setOption({
color:['#FD6C88'],
grid:{
left: '5%',
right: '5%',
bottom: '10%',
containLabel: true
},
tooltip : {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}人"
},
calculable : true,
yAxis : [
{
type : 'category',
data : ['腹痛、腹胀、腹泻','恶心、呕吐、食欲不振','肌肉酸痛、乏力','持续高烧','头痛、眼眶痛、肌肉疼','皮疹、水泡','呼吸浅促','发热、咳嗽、流口水'],
axisLine:{
lineStyle:{
color: '#FD6C88'
},
},
axisLabel : {
textStyle: {
color: '#fff'
}
}
}
],
xAxis : [
{
type : 'value',
axisLine:{
lineStyle:{
color: '#FD6C88'
},
},
splitLine: {
"show": false
},
axisLabel: {
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
},
},
}
],
series : [
{
name:'主要症状',
type:'bar',
barWidth : 20,
data:[1750,1416,1136,819,704,413,251,175],
},
]
})
//传染病发病趋势
var lineChart1 = echarts.init(document.getElementById('lineChart1'));
lineChart1.setOption({
title: {
text: '传染病趋势',
textStyle:{
fontSize:16,
color:'#ff7f50'
},
},
color:["#ff7f50"],
grid:{
left: '15%',
right: '5%',
bottom: '15%',
},
tooltip : {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}人"
},
calculable : true,
yAxis: [
{
type: 'value',
axisLine:{
lineStyle:{
color: '#ff7f50'
},
},
splitLine: {
"show": false
},
axisLabel: {
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
},
},
}
],
xAxis: [
{
type: 'category',
data : symptomName,
boundaryGap : false,
axisLine:{
lineStyle:{
color: '#ff7f50'
},
},
splitLine: {
"show": false
},
axisLabel: {
// interval:0,
// rotate:40,
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
},
},
}
],
series : [
{
name:'传染病人数',
type:'line',
smooth:true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data:[120, 132, 101, 134, 90, 230, 210,120, 132, 101, 134, 90]
},
]
})
//主要疾病排行
var histogramChart3 = echarts.init(document.getElementById('histogramChart3'));
histogramChart3.setOption({
grid: {
top: '12%',
left: '30%'
},
xAxis: {
show: false
},
yAxis: [{
show: true,
data: ['抑郁症','高血压','痔疮','肺癌','子宫肌瘤 ','乙肝','水痘','肺结核'],
inverse: true,
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#fff',
formatter: (value, index) => {
return [
`{lg|${index+1}} ` + '{title|' + value + '} '
].join('\n')
},
rich: {
lg: {
backgroundColor: '#339911',
color: '#fff',
borderRadius: 15,
// padding: 5,
align: 'center',
width: 15,
height: 15
},
}
},
}, {
show: true,
inverse: true,
data: [2000, 1800, 1200, 1100,900,900,800,700],
axisLabel: {
textStyle: {
fontSize: 12,
color: '#fff',
},
},
axisLine: {
show: false
},
splitLine: {
show: false
},
axisTick: {
show: false
},
}],
series: [{
name: '条',
type: 'bar',
yAxisIndex: 0,
data: [20,18,12,11,9,9,8,7],
barWidth: 10,
itemStyle: {
normal: {
barBorderRadius: 20,
color: function(params) {
var num = myColor.length;
return myColor[params.dataIndex % num]
},
}
},
label: {
normal: {
show: true,
position: 'inside',
formatter: '{c}%'
}
},
}, {
name: '框',
type: 'bar',
yAxisIndex: 1,
barGap: '-100%',
data: [100, 100, 100, 100,100, 100, 100, 100],
barWidth: 15,
itemStyle: {
normal: {
color: 'none',
borderColor: '#00c1de',
borderWidth: 1,
barBorderRadius: 15,
}
}
}, ]
})
//疾病发病趋势
var lineChart2 = echarts.init(document.getElementById('lineChart2'));
lineChart2.setOption({
title: {
text: '疾病发病趋势',
textStyle:{
fontSize:16,
color:'#32cd32'
},
x:"center"
},
color:["#32cd32"],
grid:{
left: '15%',
right: '5%',
bottom: '25%',
},
tooltip : {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}人"
},
calculable : true,
yAxis: [
{
type: 'value',
axisLine:{
lineStyle:{
color: '#32cd32'
},
},
splitLine: {
"show": false
},
axisLabel: {
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
},
},
}
],
xAxis: [
{
type: 'category',
data : symptomName,
boundaryGap : false,
axisLine:{
lineStyle:{
color: '#32cd32'
},
},
splitLine: {
"show": false
},
axisLabel: {
// interval:0,
// rotate:40,
textStyle: {
color: '#fff'
},
formatter: function (value) {
return value + ""
},
},
}
],
series : [
{
name:'疾病发病人数',
type:'line',
smooth:true,
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data:[520, 232,701, 434, 190, 230, 210,120, 132, 101, 134, 890]
},
]
})
//年龄分布
var pieChart1 = echarts.init(document.getElementById('pieChart1'));
pieChart1.setOption({
color:["#32cd32","#ff7f50","#87cefa","#FD6C88","#4b5cc4","#faff72"],
tooltip : {
trigger: 'item',
formatter: "{a}<br/>{b}<br/>{c}人"
},
calculable : true,
series : [
{
name:'发病人数',
type:'pie',
radius : [30, 110],
center : ['50%', '50%'],
roseType : 'area',
x: '50%',
sort : 'ascending',
data:[
{value:10, name:'婴儿(1-3岁)'},
{value:5, name:'少儿(4-10岁)'},
{value:15, name:'少年(10-18岁)'},
{value:25, name:'青年(18-45岁)'},
{value:125, name:'中年(45-60岁)'},
{value:175, name:'老年(60岁以上)'},
]
}
]
})
//性别分布
var labelFromatter = {
normal : {
label : {
position : 'center',
formatter : function (params){
console.log(params)
if(params.name == "女性"){
return "女性"+":"+(params.percent + '%')
}else{
return "男性"+":"+(params.percent + '%')
}
},
},
labelLine : {
show : false
}
},
};
var pieChart2 = echarts.init(document.getElementById('pieChart2'));
pieChart2.setOption({
color: ['#87cefa','#FD6C88'],
tooltip : {
trigger: 'item',
formatter: "{b}({c})<br/>{d}%"
},
series : [
{
type : 'pie',
center : ['50%', '50%'],
radius : [55, 95],
x: '0%', // for funnel
itemStyle : labelFromatter,
data : [
{name:'男性', value:158},
{name:'女性', value:142},
]
},
],
})
}
效果展示
注册信息会生成到对应的数据库中
完整代码连接
从安装软件到flask框架搭建可视化大屏(二)——创建一个flask页面,搭建可视化大屏,零基础也可以学会-CSDN博客https://blog.csdn.net/weixin_66547608/article/details/145670445?sharetype=blogdetail&sharerId=145670445&sharerefer=PC&sharesource=weixin_66547608&spm=1011.2480.3001.8118
https://download.csdn.net/download/weixin_66547608/90392925https://download.csdn.net/download/weixin_66547608/90392925