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 初始版本、基础数据导入、可视化展示

许可证

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


致谢

相关推荐
Byron Loong1 天前
【c++】为什么有了dll和.h,还需要包含lib
java·开发语言·c++
WL_Aurora1 天前
Python 算法基础篇之集合
python·算法
独隅1 天前
CodeX + Visual Studio Code 联动的全面指南
开发语言·php
坚果派·白晓明1 天前
【鸿蒙PC三方库移植适配框架解读系列】第一篇:Lycium C/C++ 三方库适配 — 概述与环境配置
c语言·开发语言·c++·harmonyos·开源鸿蒙·三方库·c/c++三方库
头歌实践平台1 天前
招聘大数据可视化
大数据·python
爱吃小白兔的猫1 天前
LPA算法详解:一种近线性时间的图社区发现方法
开发语言·php
Cloud_Shy6181 天前
Python 数据分析基础入门:《Excel Python:飞速搞定数据分析与处理》学习笔记系列(第八章 使用读写包操作 Excel 文件 上篇)
python·数据分析·excel·pandas
香蕉鼠片1 天前
算法过程中不会的
开发语言·c++
阿旭超级学得完1 天前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表