324-基于Python的中国传染病数据可视化分析系统

324-基于Python的中国传染病数据可视化分析系统

Infectious Disease Data Visualization and Analysis System


目录

  1. 项目概述
  2. 技术栈详解
  3. 系统架构
  4. 功能模块
  5. 技术实现
  6. [API 接口文档](#API 接口文档)
  7. 数据模型
  8. 项目结构
  9. 环境配置
  10. 部署指南
  11. 开发指南

项目概述

项目背景

中国传染病数据可视化分析系统是一个用于展示和分析2018-2024年中国各省份传染病数据的综合性平台。系统通过现代化的前端技术和强大的后端分析能力,为疾控中心、研究人员和公众提供直观的数据洞察。

核心功能

  • 多维度数据分析: 支持按时间、地区、疾病类型等多维度交叉分析
  • 全国地图可视化: 基于GeoJSON的省份级别数据展示
  • 趋势预测: 基于历史数据的简单趋势预测
  • 用户系统: 完整的注册、登录、个人中心功能
  • 数据收藏: 用户可收藏感兴趣的数据记录
  • 响应式设计: 适配桌面端和移动端

数据规模

指标 数值
数据年份 2018-2024 (7年)
省级行政区 34个
数据记录 10,000+ 条
分析维度 28+ 字段
疾病类型 10种























技术栈详解

后端技术栈

Django 4.2.29

Django 是一个高级 Python Web 框架,鼓励快速开发和简洁实用的设计。

核心组件:

组件 版本 说明
Django 4.2.29 Web 框架
djangorestframework 3.16.1 REST API 框架
djangorestframework-simplejwt 5.3.1 JWT 认证
django-cors-headers 4.9.0 跨域资源共享
django-simpleui 2024.4.1 Admin 美化主题
PyMySQL 1.1.1 MySQL 驱动
python-dotenv 1.0.1 环境变量管理

Django Apps 架构:

复制代码
backend/
├── core/           # 核心配置 (settings, urls, wsgi)
├── analytics/      # 数据分析服务
├── datasets/       # 数据模型与管理
└── accounts/      # 用户认证系统
Django REST Framework

基于 Django 的强大灵活的 REST API 工具包。

核心特性:

  • 序列化器 (Serializers) - 对象与JSON互转
  • 视图集 (ViewSets) - CRUD操作的快速实现
  • 路由 (Routers) - 自动生成URL路由
  • 认证 (Authentication) - 多种认证方式支持
  • 权限 (Permissions) - 细粒度权限控制
  • 限流 (Throttling) - API请求频率限制
JWT 认证 (djangorestframework-simplejwt)

使用 JSON Web Tokens 实现无状态认证。

Token 结构:

python 复制代码
{
    "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
}

配置参数:

参数 说明
ACCESS_TOKEN_LIFETIME 1小时 访问令牌有效期
REFRESH_TOKEN_LIFETIME 7天 刷新令牌有效期
ROTATE_REFRESH_TOKENS True 刷新时轮换令牌
BLACKLIST_AFTER_ROTATION True 旧刷新令牌加入黑名单

前端技术栈

Vue 3

渐进式 JavaScript 框架,采用 Composition API。

核心特性:

  • 响应式数据绑定
  • 组件化开发
  • 组合式 API (Composition API)
  • 单文件组件 (.vue)

依赖包:

版本 说明
vue ^3.x 核心框架
vue-router ^4.x 路由管理
pinia ^2.x 状态管理
echarts ^5.x 数据可视化
axios ^1.x HTTP 客户端
Pinia 状态管理

Vue 3 推荐的状态管理解决方案。

Store 结构:

javascript 复制代码
// stores/auth.js
export const useAuthStore = defineStore('auth', {
  state: () => ({ user: null, token: null }),
  getters: { isLoggedIn: (state) => !!state.token },
  actions: { login(), logout(), fetchProfile() }
})
ECharts 5

百度开源的数据可视化图表库。

支持的图表类型:

  • 折线图 (line)
  • 柱状图 (bar)
  • 饼图 (pie)
  • 散点图 (scatter)
  • 地图 (map)
  • 雷达图 (radar)
  • 热力图 (heatmap)
  • K线图 (candlestick)
Vite 5

新一代前端构建工具。

核心优势:

  • 极快的热更新 (HMR)
  • 基于 ESM 的开发服务器
  • 智能化依赖预构建
  • 插件化的构建机制

数据库

MySQL 8.x

关系型数据库,存储系统核心数据。

数据库配置:

python 复制代码
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "design_324_infectious",
        "USER": "root",
        "PASSWORD": "123456",
        "HOST": "127.0.0.1",
        "PORT": 3306,
        "OPTIONS": {
            "charset": "utf8mb4",
            "init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
        },
    }
}
SQLite (开发环境)

轻量级数据库,开发环境下可选。

python 复制代码
DB_ENGINE = os.getenv("DB_ENGINE", "mysql")
if DB_ENGINE == "sqlite":
    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": BASE_DIR / "db.sqlite3",
        }
    }

系统架构

整体架构图

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                         用户端浏览器                              │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                        Vue 3 前端应用                            │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    AppShell.vue                            │   │
│  │  ┌───────────┬───────────┬───────────┬─────────────┐    │   │
│  │  │  总览页   │ 疾病洞察  │ 区域研判  │  数据检索   │    │   │
│  │  └───────────┴───────────┴───────────┴─────────────┘    │   │
│  └─────────────────────────────────────────────────────────┘   │
│         │                │                │                    │
│         ▼                ▼                ▼                    │
│  ┌────────────┐   ┌────────────┐   ┌────────────┐              │
│  │Auth Store  │   │Filters    │   │Favorites  │              │
│  │(认证状态)  │   │Store      │   │Store      │              │
│  └────────────┘   │(筛选状态) │   │(收藏状态) │              │
│                   └────────────┘   └────────────┘              │
│                           │                                    │
│                           ▼                                    │
│                   ┌─────────────┐                              │
│                   │  API Service │                              │
│                   │  (Axios)    │                              │
│                   └─────────────┘                              │
└─────────────────────────────────────────────────────────────────┘
                                │ HTTP/JWT
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                       Django 后端 API                            │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                   Django REST Framework                  │   │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  │   │
│  │  │Analytics│  │Datasets │  │Accounts │  │ SimpleUI│  │   │
│  │  │ Views   │  │ Models  │  │  Views  │  │  Admin  │  │   │
│  │  └────┬────┘  └────┬────┘  └────┬────┘  └─────────┘  │   │
│  │       │             │           │                      │   │
│  │       └─────────────┴───────────┘                      │   │
│  │                     │                                    │   │
│  │              Services Layer                              │   │
│  │   (build_overview_response, build_disease_response...)   │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           │                                    │
│                           ▼                                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                    MySQL / SQLite                        │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐      │   │
│  │  │ infectious_ │  │ auth_user   │  │ accounts_  │      │   │
│  │  │ disease_    │  │             │  │ favorites   │      │   │
│  │  │ records    │  │             │  │ user_profiles│     │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘      │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

前端路由架构

复制代码
/ (根路由)
├── /login                    # 登录页 (公开)
├── /register                # 注册页 (公开)
└── /app                      # 应用壳 (需认证)
    ├── /app/overview        # 总览页面
    ├── /app/disease         # 疾病洞察页面
    ├── /app/region          # 区域研判页面
    ├── /app/records         # 数据检索页面
    └── /app/profile         # 个人中心页面

数据流向

复制代码
用户操作 → Vue组件 → Pinia Store → API Service → Django View
                                                         │
                                                         ▼
用户界面 ← ECharts ← Serializer ← Services ← Database

功能模块

1. 数据管理模块

1.1 数据模型

InfectiousDiseaseRecord 模型:

python 复制代码
class InfectiousDiseaseRecord(models.Model):
    # 时间维度
    year = models.PositiveSmallIntegerField(db_index=True)      # 年份
    month = models.PositiveSmallIntegerField(db_index=True)      # 月份
    season = models.CharField(max_length=8, db_index=True)       # 季节

    # 地理维度
    province = models.CharField(max_length=16, db_index=True)   # 省份
    city_tier = models.CharField(max_length=8, db_index=True)    # 城市等级

    # 疾病维度
    disease_type = models.CharField(max_length=24, db_index=True)  # 疾病类型

    # 人口指标
    population_density = models.PositiveIntegerField()           # 人口密度
    urbanization_rate = models.FloatField()                      # 城市化率
    elderly_population_rate = models.FloatField()                # 老年人口比例
    children_population_rate = models.FloatField()               # 儿童人口比例

    # 环境指标
    avg_temperature = models.FloatField()                       # 平均温度
    monthly_rainfall = models.FloatField()                       # 月降水量
    relative_humidity = models.PositiveSmallIntegerField()       # 相对湿度

    # 医疗指标
    vaccination_rate = models.FloatField()                        # 疫苗接种率
    medical_beds_per_10k = models.FloatField()                  # 每万人床位数
    doctors_per_1k = models.FloatField()                       # 每千人医生数
    hospital_count = models.PositiveIntegerField()               # 医院数量

    # 流动指标
    mobility_index = models.FloatField()                         # 人口流动指数

    # 疫情指标
    hygiene_level = models.PositiveSmallIntegerField()           # 卫生等级
    response_level = models.PositiveSmallIntegerField()          # 响应等级
    monthly_cases = models.PositiveIntegerField()               # 月度病例数
    monthly_deaths = models.PositiveIntegerField()             # 月度死亡数
    monthly_recoveries = models.PositiveIntegerField()          # 月度康复数
    recovery_rate = models.FloatField()                          # 康复率
    mortality_rate = models.FloatField()                        # 死亡率
    transmission_speed = models.FloatField()                     # 传播速度
    is_high_risk = models.BooleanField(default=False, db_index=True)  # 高风险标记

    # 系统字段
    record_hash = models.CharField(max_length=64, unique=True)  # 数据哈希
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
1.2 数据导入机制

CSV导入命令:

bash 复制代码
python manage.py import_infectious_csv --truncate

导入流程:

复制代码
1. 读取CSV文件 (指定编码UTF-8)
       │
       ▼
2. 解析表头映射 (CSV_FIELD_MAPPING)
       │
       ▼
3. 类型转换 (FIELD_CASTERS)
       │
       ▼
4. 生成数据哈希 (SHA256)
       │
       ▼
5. 批量插入数据库 (batch_size=2000)
       │
       ▼
6. 去重处理 (unique_together约束)

核心代码实现:

python 复制代码
# 数据哈希生成
record_hash = hashlib.sha256(
    f"{year}{month}{province}{disease_type}".encode()
).hexdigest()

# 批量插入优化
InfectiousDiseaseRecord.objects.bulk_create(
    records, ignore_conflicts=True
)
1.3 数据常量配置

省份名称映射 (解决与GeoJSON不匹配问题):

python 复制代码
PROVINCE_GEOJSON_NAMES = {
    # 直辖市
    "北京": "北京市",
    "上海": "上海市",
    "天津": "天津市",
    "重庆": "重庆市",
    # 自治区
    "内蒙古": "内蒙古自治区",
    "广西": "广西壮族自治区",
    "新疆": "新疆维吾尔自治区",
    "西藏": "西藏自治区",
    "宁夏": "宁夏回族自治区",
}

2. 数据分析模块

2.1 分析服务架构
复制代码
analytics/services.py
       │
       ├── get_filter_metadata()        # 筛选器元数据
       ├── build_overview_response()     # 总览数据
       ├── build_disease_response()      # 疾病洞察数据
       ├── build_region_response()       # 区域分析数据
       └── build_records_response()     # 数据检索数据
2.2 核心分析算法
风险评分算法
python 复制代码
WEIGHT_CONFIG = {
    "cases": 0.30,         # 病例数权重
    "deaths": 0.17,        # 死亡数权重
    "transmission": 0.16,   # 传播速度权重
    "density": 0.11,        # 人口密度权重
    "mobility": 0.10,        # 流动指数权重
    "vaccination": 0.09,    # 疫苗接种率权重 (反向)
    "response": 0.07,        # 响应等级权重 (反向)
}

def attach_risk_scores(items):
    # 1. 归一化处理 (Min-Max)
    normalized_values[metric] = (value - min) / (max - min)

    # 2. 反向处理 (疫苗、响应等级越高风险越低)
    if metric in {"vaccination", "response"}:
        score = 1 - score

    # 3. 加权求和
    risk_score = sum(normalized * weight for weight in WEIGHT_CONFIG)

    # 4. 风险分层
    if risk_score >= 70: tier = "极高风险"
    elif risk_score >= 50: tier = "高风险"
    elif risk_score >= 30: tier = "中风险"
    else: tier = "低风险"
皮尔逊相关系数
python 复制代码
def pearson_correlation(pairs):
    if len(pairs) < 2:
        return 0

    xs, ys = zip(*pairs)
    mean_x = sum(xs) / len(xs)
    mean_y = sum(ys) / len(ys)

    numerator = sum((x - mean_x) * (y - mean_y) for x, y in zip(xs, ys))
    denominator_x = sqrt(sum((x - mean_x) ** 2 for x in xs))
    denominator_y = sqrt(sum((y - mean_y) ** 2 for y in ys))
    denominator = denominator_x * denominator_y

    return 0 if not denominator else numerator / denominator
简单趋势预测
python 复制代码
def predict_next_year(yearly_series):
    # 1. 取最近3年数据
    recent = yearly_series[-3:]

    # 2. 计算年均增长率
    for i in range(1, len(recent)):
        growth = (curr - prev) / prev
        avg_growth += growth
    avg_growth_rate = avg_growth / (len(recent) - 1)

    # 3. 预测下一年
    last_cases = yearly_series[-1]["cases"]
    predicted = last_cases * (1 + avg_growth_rate)

    return {
        "year": last_year + 1,
        "predictedCases": max(0, int(predicted)),
        "growthRate": round(avg_growth_rate * 100, 2),
        "trend": "上升" if avg_growth_rate > 0 else "下降",
        "confidence": "高" if len(recent) >= 3 else "中",
    }
2.3 总览页面 (OverviewView)

API 返回数据结构:

javascript 复制代码
{
  kpis: {
    recordCount: 10000,           // 记录总数
    totalCases: 500000,            // 累计病例
    totalDeaths: 5000,            // 累计死亡
    totalRecoveries: 450000,        // 累计康复
    avgRecoveryRate: 85.5,         // 平均康复率
    avgVaccinationRate: 72.3,       // 平均接种率
    highRiskShare: 23.5,           // 高风险占比
  },
  mapData: [                       // 地图数据
    { name: "北京市", shortName: "北京", value: 15000, riskScore: 85.3 },
    // ...
  ],
  yearlyTrend: [                    // 年度趋势
    { year: 2018, cases: 60000, deaths: 600, recoveries: 54000 },
    // ...
  ],
  diseaseRanking: [                 // 疾病排名
    { disease_type: "新冠肺炎", cases: 150000, deaths: 1500 },
    // ...
  ],
  mortalityTrend: [                // 死亡率趋势
    { year: 2018, mortality_rate: 1.2 },
    // ...
  ],
  responseDistribution: [           // 响应等级分布
    { response_level: 1, cases: 10000, count: 200 },
    // ...
  ],
  riskTiers: {                     // 风险分层
    "极高风险": ["广东", "浙江", ...],
    "高风险": [...],
    // ...
  },
  prediction: {                    // 趋势预测
    year: 2025,
    predictedCases: 520000,
    growthRate: 4.2,
    trend: "上升",
    confidence: "高"
  }
}
2.4 疾病洞察页面 (DiseaseInsightsView)

核心图表:

  1. 月度趋势图 - 折线图展示病例时间变化
  2. 疾病特征雷达图 - 多维度疾病特征对比
  3. 疾病-省份矩阵 - 热力图展示跨维度分析
  4. 省份死亡率对比 - 横向柱状图
2.5 区域研判页面 (RegionAnalysisView)

核心图表:

  1. 风险地图 - GeoJSON地图按风险评分着色
  2. 省份排名 - 多维度综合评分排名
  3. 城市等级对比 - 按城市等级分组分析
  4. 医疗资源散点 - 病床数/医生数与病例相关性
  5. 人口结构分析 - 城市化率、老年/儿童比例

3. 用户认证模块

3.1 用户模型扩展
python 复制代码
# accounts/models.py
class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    nickname = models.CharField(max_length=50, blank=True)
    avatar = models.URLField(max_length=500, blank=True)
    phone = models.CharField(max_length=20, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class Favorite(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    record = models.ForeignKey("datasets.InfectiousDiseaseRecord")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ["user", "record"]  # 防止重复收藏
3.2 JWT 认证流程
复制代码
1. 用户注册/登录
           │
           ▼
2. 服务器验证凭据
           │
           ▼
3. 生成 Access Token (1小时) + Refresh Token (7天)
           │
           ▼
4. 前端存储 Token (localStorage)
           │
           ▼
5. 请求时附加 Token (Authorization: Bearer xxx)
           │
           ▼
6. Access Token 过期时,使用 Refresh Token 刷新
3.3 前端认证状态管理
javascript 复制代码
// stores/auth.js
export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: null,
    accessToken: localStorage.getItem('accessToken'),
    refreshToken: localStorage.getItem('refreshToken'),
  }),
  getters: {
    isLoggedIn: (state) => !!state.accessToken,
  },
  actions: {
    async login(username, password) {
      const data = await login(username, password)
      this.accessToken = data.tokens.access
      this.refreshToken = data.tokens.refresh
      this.user = data.user
    },
    async logout() {
      await logout()
      this.accessToken = null
      this.refreshToken = null
      this.user = null
    }
  }
})

4. 后台管理模块

4.1 Django Admin 配置

使用 SimpleUI 美化后台界面。

python 复制代码
# core/settings.py
INSTALLED_APPS = [
    "simpleui",  # 必须放在第一位
    "django.contrib.admin",
    # ...
]
4.2 模型中文配置
python 复制代码
# accounts/models.py
class Meta:
    verbose_name = "用户资料"
    verbose_name_plural = "用户资料"

class Favorite(models.Model):
    class Meta:
        verbose_name = "收藏"
        verbose_name_plural = "收藏"
4.3 Admin 站点配置
python 复制代码
# accounts/admin.py
@admin.register(Favorite)
class FavoriteAdmin(admin.ModelAdmin):
    list_display = ["user", "record", "created_at"]
    search_fields = ["user__username"]

技术实现

1. 前端 ECharts 图表配置

地图配置 (GeoJSON)
javascript 复制代码
// OverviewView.vue
const mapOption = computed(() => ({
  series: [{
    type: 'map',
    map: 'china',
    data: payload.mapData.map(item => ({
      name: item.name,        // "北京市"
      value: item.value,
    })),
    label: { show: true },
    itemStyle: {
      areaColor: {
        // 根据风险评分着色
        color: getRiskColor(item.riskScore)
      }
    }
  }]
}))
风险评分颜色映射
javascript 复制代码
function getRiskColor(score) {
  if (score >= 70) return '#c23531'  // 极高风险 - 红色
  if (score >= 50) return '#d48265'   // 高风险 - 橙色
  if (score >= 30) return '#e6b600' // 中风险 - 黄色
  return '#50a3ba'                     // 低风险 - 蓝色
}

2. 省份名称转换

数据库中使用短名称(如"北京"),GeoJSON中使用全称(如"北京市")。

python 复制代码
# services.py
def to_geojson_name(province_name):
    return PROVINCE_GEOJSON_NAMES.get(province_name, province_name)

# 使用示例
mapData = [
    {"name": to_geojson_name(item["province"]), "value": item["cases"]}
    for item in province_groups
]

3. 全局筛选联动

使用 Pinia 实现全局状态同步。

javascript 复制代码
// stores/filters.js
export const useFiltersStore = defineStore('filters', {
  state: () => ({
    filters: {
      year: [2024],
      month: [],
      province: [],
      disease: [],
      season: [],
      cityTier: [],
      highRiskOnly: false,
    }
  }),
  getters: {
    activeCount: (state) =>
      Object.values(state.filters).filter(v => v.length > 0).length
  },
  actions: {
    setFilter(key, value) {
      this.filters[key] = value
    }
  }
})

4. 分页查询

python 复制代码
# services.py
def build_records_response(filters, params):
    page = max(int(params.get("page", 1)), 1)
    page_size = min(max(int(params.get("pageSize", 12)), 1), 100)

    paginator = Paginator(queryset, page_size)
    page_obj = paginator.get_page(page)

    return {
        "items": [record_to_dict(record) for record in page_obj],
        "pagination": {
            "page": page_obj.number,
            "pageSize": page_size,
            "pages": paginator.num_pages,
            "total": paginator.count,
        }
    }

API 接口文档

基础信息

项目 说明
Base URL http://localhost:8000/api/
数据格式 JSON
认证方式 JWT Bearer Token

认证接口

POST /api/auth/register - 用户注册

请求:

json 复制代码
{
  "username": "testuser",
  "password": "password123",
  "password_confirm": "password123",
  "email": "test@example.com"
}

响应 (201 Created):

json 复制代码
{
  "user": {
    "id": 1,
    "username": "testuser",
    "email": "test@example.com"
  },
  "tokens": {
    "refresh": "eyJ0eXAiOiJKV1...",
    "access": "eyJ0eXAiOiJKV1..."
  }
}
POST /api/auth/login - 用户登录

请求:

json 复制代码
{
  "username": "admin",
  "password": "admin123"
}

响应 (200 OK):

json 复制代码
{
  "user": {
    "id": 1,
    "username": "admin",
    "email": "admin@example.com"
  },
  "tokens": {
    "refresh": "eyJ0eXAiOiJKV1...",
    "access": "eyJ0eXAiOiJKV1..."
  }
}
POST /api/auth/logout - 用户登出

请求头 : Authorization: Bearer <access_token>

请求:

json 复制代码
{
  "refresh": "eyJ0eXAiOiJKV1..."
}

响应 (200 OK):

json 复制代码
{
  "message": "登出成功"
}
GET /api/auth/profile - 获取个人信息

请求头 : Authorization: Bearer <access_token>

响应 (200 OK):

json 复制代码
{
  "id": 1,
  "username": "admin",
  "email": "admin@example.com",
  "profile": {
    "nickname": "",
    "avatar": "",
    "phone": ""
  }
}
PUT /api/auth/profile - 更新个人信息

请求头 : Authorization: Bearer <access_token>

请求:

json 复制代码
{
  "nickname": "新昵称",
  "phone": "13800138000"
}

响应 (200 OK):

json 复制代码
{
  "id": 1,
  "username": "admin",
  "profile": {
    "nickname": "新昵称",
    "phone": "13800138000"
  }
}
POST /api/auth/change-password - 修改密码

请求:

json 复制代码
{
  "old_password": "oldpass123",
  "new_password": "newpass123"
}

响应 (200 OK):

json 复制代码
{
  "message": "密码修改成功"
}

数据接口

GET /api/filters - 获取筛选器元数据

响应:

json 复制代码
{
  "filters": {
    "years": [2018, 2019, 2020, 2021, 2022, 2023, 2024],
    "months": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
    "provinces": ["北京", "天津", "河北", ...],
    "diseases": ["新冠肺炎", "流感", "肺结核", ...],
    "seasons": ["春季", "夏季", "秋季", "冬季"],
    "cityTiers": ["一线", "新一线", "二线", "三线", "四线", "五线"]
  },
  "fieldLabels": { ... },
  "valueAliases": { ... }
}
GET /api/overview - 总览数据

查询参数:

参数 类型 说明
year int[] 年份筛选
province string[] 省份筛选
disease string[] 疾病类型筛选

响应 : 参见 总览页面数据结构

GET /api/disease-insights - 疾病洞察数据

查询参数:

参数 类型 说明
disease string 疾病类型(必填)

响应 : 参见 疾病洞察数据结构

GET /api/region-analysis - 区域分析数据

响应 : 参见 区域分析数据结构

GET /api/records - 数据检索

查询参数:

参数 类型 说明
page int 页码(默认1)
pageSize int 每页条数(默认12,最大100)
sortBy string 排序字段
order string 排序方向 (asc/desc)

响应:

json 复制代码
{
  "items": [
    {
      "id": 1,
      "year": 2024,
      "month": 1,
      "province": "北京",
      "diseaseType": "新冠肺炎",
      "monthlyCases": 5000,
      ...
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 12,
    "pages": 100,
    "total": 1200
  }
}

收藏接口

GET /api/favorites - 获取收藏列表

响应:

json 复制代码
[
  {
    "id": 1,
    "record_id": 10,
    "created_at": "2024-04-03T10:00:00Z",
    "record": { ... }
  }
]
POST /api/favorites/add - 添加收藏

请求:

json 复制代码
{
  "record_id": 10
}

响应 (201 Created):

json 复制代码
{
  "id": 1,
  "record_id": 10
}
DELETE /api/favorites/{record_id} - 删除收藏

响应 (204 No Content)


数据模型

模型关系图

复制代码
User
├── UserProfile (1:1)
└── Favorite (1:N)
    └── InfectiousDiseaseRecord (N:1)

数据库表结构

infectious_disease_records
字段 类型 索引 说明
id BIGINT PK 主键
year SMALLINT idx 年份
month SMALLINT idx 月份
province VARCHAR(16) idx 省份
city_tier VARCHAR(8) idx 城市等级
disease_type VARCHAR(24) idx 疾病类型
population_density INT - 人口密度
avg_temperature FLOAT - 平均温度
monthly_rainfall FLOAT - 月降水量
vaccination_rate FLOAT - 疫苗接种率
medical_beds_per_10k FLOAT - 每万人床位
monthly_cases INT - 月度病例
monthly_deaths INT - 月度死亡
mortality_rate FLOAT - 死亡率
is_high_risk BOOL idx 高风险标记
record_hash VARCHAR(64) UNIQUE 数据哈希

复合索引:

  • (year, month)
  • (province, disease_type)
  • (season, city_tier)
  • (is_high_risk, year)
auth_user

Django 内置用户表。

字段 类型 说明
id INT 主键
username VARCHAR(150) 用户名
password VARCHAR(128) 密码哈希
email VARCHAR(254) 邮箱
is_staff BOOL 是否为员工
is_superuser BOOL 是否为超级用户
accounts_userprofile
字段 类型 说明
id BIGINT 主键
user_id INT 外键 -> auth_user
nickname VARCHAR(50) 昵称
avatar VARCHAR(500) 头像URL
phone VARCHAR(20) 电话
accounts_favorite
字段 类型 说明
id BIGINT 主键
user_id INT 外键 -> auth_user
record_id BIGINT 外键 -> infectious_disease_records
created_at DATETIME 创建时间

约束: UNIQUE(user_id, record_id)


项目结构

复制代码
infectious/
├── backend/                         # Django 后端项目
│   ├── core/                       # 核心配置模块
│   │   ├── __init__.py
│   │   ├── settings.py             # Django 设置文件
│   │   │   ├── INSTALLED_APPS     # 已安装应用
│   │   │   ├── DATABASES          # 数据库配置
│   │   │   ├── REST_FRAMEWORK     # DRF 配置
│   │   │   ├── SIMPLE_JWT         # JWT 配置
│   │   │   └── CORS_ALLOWED_ORIGINS  # CORS 配置
│   │   ├── urls.py                # 根路由配置
│   │   ├── wsgi.py                # WSGI 入口
│   │   └── asgi.py                # ASGI 入口
│   │
│   ├── analytics/                  # 数据分析应用
│   │   ├── __init__.py
│   │   ├── apps.py                # 应用配置
│   │   ├── models.py              # 模型定义(本应用为空)
│   │   ├── services.py            # ★ 核心分析服务
│   │   │   ├── parse_filters()    # 筛选参数解析
│   │   │   ├── apply_filters()    # 筛选条件应用
│   │   │   ├── attach_risk_scores()  # 风险评分计算
│   │   │   ├── pearson_correlation()  # 相关系数
│   │   │   ├── build_overview_response()   # 总览数据
│   │   │   ├── build_disease_response()   # 疾病洞察
│   │   │   ├── build_region_response()    # 区域分析
│   │   │   └── build_records_response()   # 数据检索
│   │   ├── views.py               # API 视图
│   │   ├── urls.py               # 路由配置
│   │   ├── admin.py              # Admin 配置
│   │   └── tests.py              # 单元测试
│   │
│   ├── datasets/                  # 数据管理应用
│   │   ├── __init__.py
│   │   ├── apps.py
│   │   ├── models.py             # ★ 数据模型
│   │   ├── constants.py           # ★ 常量配置
│   │   │   ├── CSV_FIELD_MAPPING  # CSV字段映射
│   │   │   ├── FIELD_LABELS      # 字段中英文标签
│   │   │   ├── PROVINCE_ALIASES  # 省份英文别名
│   │   │   ├── DISEASE_ALIASES   # 疾病英文别名
│   │   │   ├── SEASON_ORDER      # 季节顺序
│   │   │   └── CITY_TIER_ORDER   # 城市等级顺序
│   │   ├── views.py
│   │   ├── admin.py              # Admin 配置
│   │   ├── management/
│   │   │   └── commands/
│   │   │       └── import_infectious_csv.py  # ★ CSV导入命令
│   │   └── migrations/
│   │
│   ├── accounts/                   # 用户账户应用
│   │   ├── __init__.py
│   │   ├── apps.py
│   │   ├── models.py             # ★ 用户扩展模型
│   │   │   ├── UserProfile       # 用户资料
│   │   │   └── Favorite          # 收藏
│   │   ├── serializers.py        # ★ DRF 序列化器
│   │   │   ├── UserSerializer
│   │   │   ├── RegisterSerializer
│   │   │   ├── UserProfileSerializer
│   │   │   ├── FavoriteSerializer
│   │   │   └── ChangePasswordSerializer
│   │   ├── views.py              # ★ API 视图
│   │   │   ├── RegisterView      # 注册
│   │   │   ├── LoginView         # 登录
│   │   │   ├── LogoutView       # 登出
│   │   │   ├── ProfileView       # 个人信息
│   │   │   ├── ChangePasswordView  # 修改密码
│   │   │   ├── FavoriteListView    # 收藏列表
│   │   │   ├── FavoriteCreateView   # 添加收藏
│   │   │   └── FavoriteDeleteView  # 删除收藏
│   │   ├── urls.py               # 路由配置
│   │   └── admin.py              # Admin 配置
│   │
│   ├── staticfiles/              # 收集的静态文件
│   │   └── admin/
│   │       └── simpleui-x/       # SimpleUI 静态资源
│   │
│   ├── manage.py                 # Django 管理脚本
│   └── requirements.txt          # Python 依赖
│
├── frontend/                       # Vue 前端项目
│   ├── public/
│   │   └── index.html           # HTML 入口
│   │
│   ├── src/
│   │   ├── main.js             # ★ Vue 入口
│   │   ├── App.vue             # 根组件
│   │   ├── style.css           # 全局样式
│   │   │
│   │   ├── views/             # ★ 页面组件
│   │   │   ├── LoginView.vue   # 登录页
│   │   │   ├── RegisterView.vue # 注册页
│   │   │   ├── OverviewView.vue  # 总览页
│   │   │   ├── DiseaseInsightsView.vue  # 疾病洞察
│   │   │   ├── RegionAnalysisView.vue    # 区域研判
│   │   │   ├── RecordsView.vue          # 数据检索
│   │   │   └── ProfileView.vue           # 个人中心
│   │   │
│   │   ├── components/         # 公共组件
│   │   │   ├── AppShell.vue   # 应用壳组件
│   │   │   ├── GlobalFilterBar.vue  # 全局筛选栏
│   │   │   └── DataTable.vue  # 数据表格
│   │   │
│   │   ├── stores/            # ★ Pinia 状态管理
│   │   │   ├── auth.js        # 认证状态
│   │   │   ├── filters.js     # 筛选状态
│   │   │   └── favorites.js   # 收藏状态
│   │   │
│   │   ├── services/          # API 服务层
│   │   │   └── api.js         # ★ Axios 封装
│   │   │                       # - 请求拦截器
│   │   │                       # - 响应拦截器
│   │   │                       # - Token 管理
│   │   │
│   │   ├── router/            # 路由配置
│   │   │   └── index.js       # ★ 路由定义
│   │   │                       # - 路由守卫
│   │   │                       # - 权限控制
│   │   │
│   │   ├── utils/             # 工具函数
│   │   └── assets/            # 静态资源
│   │
│   ├── package.json          # npm 依赖
│   ├── vite.config.js        # Vite 配置
│   └── .env.example          # 环境变量示例
│
├── data/                       # 数据文件
│   └── 中国传染病数据.csv     # 原始数据
│
├── scripts/                    # 脚本目录
│   └── init_mysql.sql         # MySQL 初始化脚本
│
├── .env.example               # 环境变量示例
├── .gitignore                 # Git 忽略配置
└── README.md                  # 项目文档

环境配置

后端环境变量

bash 复制代码
# .env 文件 (位于 infectious/ 目录)

# Django 核心配置
DJANGO_SECRET_KEY=your-secret-key-change-in-production
DJANGO_DEBUG=true
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost

# 数据库配置 (MySQL)
DB_ENGINE=mysql
DB_NAME=design_324_infectious
DB_USER=root
DB_PASSWORD=123456
DB_HOST=127.0.0.1
DB_PORT=3306

# 或使用 SQLite (开发环境)
# DB_ENGINE=sqlite
# SQLITE_NAME=backend/db.sqlite3

# CORS 配置
CORS_ALLOWED_ORIGINS=http://127.0.0.1:5173,http://localhost:5173

# 数据文件路径
DATA_CSV_PATH=./data/中国传染病数据.csv

前端环境变量

bash 复制代码
# .env 文件 (位于 frontend/ 目录)
VITE_API_BASE_URL=http://localhost:8000/api

部署指南

1. 环境准备

Python 环境:

bash 复制代码
# 推荐使用虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate   # Windows

# 安装依赖
cd backend
pip install -r requirements.txt

Node.js 环境:

bash 复制代码
# 推荐使用 nvm 管理 Node 版本
nvm install 18
nvm use 18

# 安装依赖
cd frontend
npm install

2. 数据库初始化

创建 MySQL 数据库:

sql 复制代码
-- 登录 MySQL
mysql -u root -p

-- 执行 SQL
CREATE DATABASE IF NOT EXISTS `design_324_infectious`
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;

或使用初始化脚本:

bash 复制代码
mysql -u root -p < scripts/init_mysql.sql

3. 后端部署

bash 复制代码
cd backend

# 1. 执行数据库迁移
python manage.py migrate

# 2. 导入初始数据
python manage.py import_infectious_csv --truncate

# 3. 创建管理员账户
python manage.py createsuperuser
# Username: admin
# Email: admin@example.com
# Password: admin123

# 4. 收集静态文件
python manage.py collectstatic

# 5. 启动开发服务器
python manage.py runserver

4. 前端部署

bash 复制代码
cd frontend

# 1. 安装依赖
npm install

# 2. 启动开发服务器
npm run dev

# 3. 构建生产版本 (可选)
npm run build

5. 访问系统

服务 地址
前端应用 http://localhost:5173
后端 API http://localhost:8000/api/
Admin 后台 http://localhost:8000/admin/
API 文档 http://localhost:8000/api/docs/ (需安装 drf-spectacular)

开发指南

添加新的分析图表

1. 后端 - 添加数据服务
python 复制代码
# analytics/services.py

def build_new_chart_data(filters):
    """新图表数据构建"""
    queryset = apply_filters(InfectiousDiseaseRecord.objects.all(), filters)

    # 数据处理逻辑
    chart_data = list(
        queryset.values('field')
        .annotate(...)
        .order_by(...)
    )

    return {
        "chartData": chart_data,
        "metadata": { ... }
    }
2. 后端 - 添加 API 端点
python 复制代码
# analytics/views.py

class NewChartView(APIView):
    permission_classes = [AllowAny]

    def get(self, request):
        filters = parse_filters(request.query_params)
        return Response(build_new_chart_data(filters))
python 复制代码
# analytics/urls.py

urlpatterns = [
    # ... existing routes
    path('new-chart/', NewChartView.as_view(), name='new-chart'),
]
3. 前端 - 添加图表组件
vue 复制代码
<!-- OverviewView.vue -->
<script setup>
import { ref, computed, onMounted } from 'vue'
import * as echarts from 'echarts'

const chartRef = ref(null)

const newChartOption = computed(() => ({
  title: { text: '新图表' },
  series: [{
    type: 'bar',
    data: payload.value.chartData
  }]
}))

onMounted(() => {
  // 初始化图表
  const chart = echarts.init(chartRef.value)
  chart.setOption(newChartOption.value)
})
</script>

<template>
  <div ref="chartRef" class="chart-container"></div>
</template>

添加新的筛选条件

1. 数据库 - 添加字段
python 复制代码
# datasets/models.py

class InfectiousDiseaseRecord(models.Model):
    # ... existing fields
    new_field = models.CharField(max_length=50, blank=True)
2. 常量 - 添加映射
python 复制代码
# datasets/constants.py

CSV_FIELD_MAPPING['新CSV字段'] = 'new_field'
FIELD_LABELS['new_field'] = {'zh': '新字段', 'en': 'New Field'}
3. 服务 - 添加筛选
python 复制代码
# analytics/services.py

QUERY_TO_FIELD['newFilter'] = 'new_field'

def parse_filters(params):
    return {
        # ... existing filters
        'newFilter': parse_multi_value(params, 'newFilter'),
    }
4. 前端 - 添加筛选组件
vue 复制代码
<!-- GlobalFilterBar.vue -->
<template>
  <div class="filter-bar">
    <!-- 现有筛选器 -->
    <select v-model="filtersStore.filters.newFilter">
      <option value="">新字段</option>
    </select>
  </div>
</template>

生产环境部署建议

Nginx 配置
nginx 复制代码
upstream backend {
    server 127.0.0.1:8000;
}

upstream frontend {
    server 127.0.0.1:5173;
}

server {
    listen 80;
    server_name yourdomain.com;

    # 前端静态文件
    location / {
        proxy_pass http://frontend;
    }

    # API 代理
    location /api {
        proxy_pass http://backend;
    }

    # Django 静态文件
    location /static {
        alias /path/to/staticfiles;
    }
}
Gunicorn 配置
bash 复制代码
# 安装 gunicorn
pip install gunicorn

# 启动 (8 workers)
gunicorn core.wsgi:application \
    --bind 127.0.0.1:8000 \
    --workers 8 \
    --timeout 120

系统截图预览

登录页面

  • 现代化玻璃拟态设计
  • 左右分栏布局
  • 动态背景光晕
  • 实时表单验证

总览页面

  • 4x3 KPI 卡片网格
  • 全国地图可视化
  • 多图表联动
  • 风险等级分层展示

疾病洞察页面

  • 月度趋势分析
  • 疾病特征雷达图
  • 跨维度矩阵热力图

区域研判页面

  • 省份风险排名
  • 医疗资源散点分析
  • 人口结构可视化

常见问题

Q: 地图省份无法显示?

A : 检查 services.py 中的 PROVINCE_GEOJSON_NAMES 映射,确保数据库省份名称与 GeoJSON 文件中的名称一致。

Q: 登录失败,提示 Token 无效?

A:

  1. 确认后端服务器正在运行
  2. 检查浏览器控制台是否有 CORS 错误
  3. 清除 localStorage 重新登录

Q: 数据导入失败?

A:

  1. 检查 CSV 文件编码(需 UTF-8)
  2. 确认 CSV 表头与 CSV_FIELD_MAPPING 一致
  3. 查看 Django 控制台错误日志

Q: SimpleUI 主题不生效?

A:

  1. 确认 simpleuiINSTALLED_APPS 第一位
  2. 执行 python manage.py collectstatic
  3. 重启 Django 服务器
  4. 清除浏览器缓存

版本历史

版本 日期 主要更新
v2.0 2024.04 全新UI设计、用户认证、数据收藏
v1.0 2024.03 初始版本、基础数据导入、可视化展示

许可证

本项目仅供学习和研究使用。


致谢

相关推荐
ZC跨境爬虫2 小时前
Playwright基础操作:元素坐标获取与坐标截图实战
python·microsoft·前端框架
源码之家2 小时前
计算机毕业设计:Python汽车销量智能分析与预测系统 Flask框架 scikit-learn 可视化 requests爬虫 AI 大模型(建议收藏)✅
人工智能·hadoop·python·算法·数据分析·flask·课程设计
普通网友2 小时前
使用Python处理计算机图形学(PIL/Pillow)
jvm·数据库·python
吕司2 小时前
Linux线程的操作
linux·服务器·开发语言
曹牧2 小时前
Java:上传文件到网页
java·开发语言
lly2024062 小时前
CSS3 3D 转换
开发语言
qiqiqi(^_×)2 小时前
pycharm Memory Settings无法保存
ide·python·pycharm
xzal122 小时前
Python 中,and 和 or 运算符的运算规则
笔记·python
gf13211112 小时前
【python_使用指定应用发送飞书卡片】
java·python·飞书