
带了几届毕业设计也接过不少同类项目的远程调试和讲解需求之后我对基于Python的适老化健康预警系统这个题目可以说非常熟悉。它几乎每年都会出现在毕设选题清单里但真正能把这个题目做出彩、答辩不被追问到冷场的同学数量其实不多。问题通常不是技术学不会而是很多人第一步就理解偏了——以为这就是一个普通的增删改查管理系统于是做出一个有点难看的管理后台。这篇文章我会按我自己实际跑通这个项目时的思路来写从需求怎么拆、数据库怎么设计、预警逻辑怎么写到前端图表怎么做、远程调试怎么配、答辩演示怎么准备全部给你过一遍。如果你正在选这个题目或者已经选了但代码还没思路照着下面这条线走基本不会跑偏。1. 适老化健康预警项目的价值边界别把题目想窄了1.1 老龄化场景下的真实需求先说为什么要做这个选题。老年人的健康风险跟年轻人最大的区别在于两点一是基础病多血压、血糖、心率这些指标本身就处在临界区间二是身体对异常的反应慢很多时候等老人自己感觉到不舒服指标早就偏离正常值一段时间了。所以健康预警不是单纯做一个记录血压的网站而是想办法从持续采集的健康数据里找出那些再拖下去可能出问题的信号。对于家里有老人的用户来说这套系统的核心价值就一句话不用天天盯着血压计系统帮你盯着指标异常了及时提醒家属。放到毕业设计的语境里这个需求翻译过来就是一个完整的业务系统有用户、有档案、有数据采集、有规则判定、有通知流转、有统计展示。你要是能把这条链路讲清楚答辩的时候就已经赢了大多数只做了几个CRUD页面的同学。1.2 为什么适老化不是简单把字体调大适老化这个词在需求文档里经常被忽略但它恰恰是这个题目的亮点。很多同学上来就把页面做得花里胡哨菜单一大堆按钮五颜六色看起来功能很全实际上完全不适合老年人用。适老化交互设计至少包含三层意思。第一层是界面密度要低。老人不像年轻人能快速扫描整个页面同一屏就放一个核心任务比如今日血压趋势或者最新一条预警提醒其他信息折叠起来不要堆在一起。第二层是信息反馈要明确。操作成功、数据异常、预警触发这些都要有醒目的视觉反馈而不是只在角落里弹一个几秒就消失的提示框。第三层是容错性要高。老人可能误触按钮、可能重复录入数据、可能忘记怎么操作系统要能容忍这些错误比如重复提交同一时间段的数据时自动去重删除之前让你二次确认。在写代码的时候这三层要求分别对应到前端布局设计、交互组件选型、后端数据校验逻辑。你不需要真的做一个给老人用的产品但你要能在答辩时说清楚我的系统在哪些地方考虑了适老化并能在界面设计上看出这个痕迹。1.3 恰当的技术边界哪些该做哪些不该碰这个题目最容易翻车的地方是有人想把预警做成AI预测声称用机器学习预测老人未来会不会心梗。先不说本科生阶段做出来的精度靠不靠谱光是把预测算法变成一个能稳定复现、能演示出效果的功能就足够耗掉你大把时间。我的建议是把系统的核心定位在规则判定异常提醒算法上做好阈值判断和趋势分析就足够了。比如血压超过140/90并持续一段时间或者心率连续三次超出正常区间就触发预警。这类逻辑实现简单、效果直观、答辩时也容易讲清楚原理。等到系统主体都稳定跑起来你还有富余时间再去考虑要不要引入机器学习做一个风险等级评估模块。把边界划清楚项目才做得完这是一个过来人给你的忠告。2. 从预警反推需求角色、流程与功能清单2.1 三种角色与权限划分我在做这类项目时第一件事不是建表而是想清楚系统里有哪几种人每种人进来能干什么。对于适老化健康预警系统最合理的角色划分是三种老人/被监护者这是数据的主人但实际使用系统的频率通常不高。他们主要负责查看自己的健康数据和预警提醒偶尔手动录入体征数据。家属/照护人这是系统的核心使用人群。他们需要查看老人的完整档案、接收预警通知、对预警进行确认和处理。管理员/医护人员负责老人档案录入与维护、配置各项指标的预警规则、查看系统运行统计、管理用户账号。在Django里角色权限可以直接用自带认证系统扩展字段或者用一个独立的Profile模型关联。不需要引入复杂的权限框架django自带的Group就能满足大部分场景。比如把家属和管理员分别建组再用装饰器login_required和user_passes_test控制页面访问。2.2 核心业务闭环一条数据从进入到归档这个系统的核心逻辑不是展示记录而是一条完整的业务闭环数据产生→数据入库→规则校验→命中预警→通知触发→家属确认→处理归档→统计分析每一步环环相扣。数据录入可以是老人手动填写也可以是系统模拟生成的规则校验是核心引擎拿到一条数据后判断是否触发预警一旦触发系统生成预警记录并通知家属家属登录看到预警后选择已确认或已处理最后所有的历史预警进入统计报表。这个闭环里最有答辩价值的点是预警处理状态流转。多数基础版毕设只做到生出预警就通知没有后续状态那你就可以在项目里多做一步让预警记录经历待处理→已确认→已办结的状态变化。这既体现了业务思考的完整度也方便你后续做统计功能。2.3 功能模块完整清单我直接给一份我在实际项目中整理的功能清单你可以照着设计自己的页面功能模块核心功能点对应技术实现用户认证注册、登录、退出、角色区分Django auth、Profile扩展老人档案管理新增老人档案、历史病史、日常备注普通CRUD 表单校验体征数据管理血压、心率、血氧、体温、血糖录入与维护ModelForm、Ajax提交预警规则配置每种指标设置阈值、比较符、持续次数配置表 规则引擎预警记录中心预警列表、状态流转、详情查看分页 状态过滤数据可视化健康趋势图、预警统计图、异常分布ECharts JsonResponse通知提醒预警触发后的站内信/页面横幅提醒Django Signal 站内消息系统管理用户管理、操作日志、系统配置django admin 自定义页面这套模块做完功能完整度完全可以覆盖丰富项目源码文档的定位也有足够的素材写出一份像样的毕业论文。3. Django技术选型与项目骨架设计3.1 为什么用Django而不是Flask或SpringBoot我见过不止一个同学在选题阶段纠结框架其实在这个题目上Django几乎是标准答案本文就是关于基于Python/Django的系统的。但为了让你在答辩时能头头是道地说清楚为什么选它我给你一个对比思路维度DjangoFlaskSpring Boot开发效率高自带ORM、Admin、认证中等很多组件要自己搭低Java生态偏重学习曲线平缓文档全平缓但缺少约束陡峭配置繁琐项目完整性自带Admin后台和迁移机制需要自己组装完善但复杂度高数据库操作强大ORM对新手友好SQLAlchemy有学习成本JPA概念多适合毕设程度最适合可以做但不推荐如果你只会Java才考虑你答辩时可以这样总结Django自带一整套Web开发的基础设施让我把主要精力集中在业务逻辑而不是重复造轮子同时Python在数据处理上有天然优势方便后续对接健康数据的分析功能。3.2 数据库模型设计从老人档案到预警记录数据模型是整个项目的根基我建议按这个思路建表。先有用户然后是老人的档案档案关联采集的健康记录健康记录关联预警规则和预警记录。一条标准的设计链路如下。from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): ROLE_CHOICES ( (elder, 老人), (family, 家属/照护人), (admin, 管理员), ) role models.CharField(max_length10, choicesROLE_CHOICES, defaultfamily) phone models.CharField(max_length20, blankTrue) class ElderlyProfile(models.Model): user models.OneToOneField(User, on_deletemodels.CASCADE, related_nameelder_profile) name models.CharField(max_length50) gender models.CharField(max_length10) birth_date models.DateField() height models.FloatField(verbose_name身高(cm), blankTrue, nullTrue) weight models.FloatField(verbose_name体重(kg), blankTrue, nullTrue) medical_history models.TextField(verbose_name既往病史, blankTrue) emergency_contact models.CharField(max_length50) emergency_phone models.CharField(max_length20) created_at models.DateTimeField(auto_now_addTrue)然后是体征数据和预警相关模型。体征数据我建议用一个统一表用指标类型字段区分这样后面扩展新指标不用建新表预警规则单独建表方便管理员在系统里配置。class HealthRecord(models.Model): INDICATOR_CHOICES ( (blood_pressure, 血压), (heart_rate, 心率), (blood_oxygen, 血氧), (blood_glucose, 血糖), (temperature, 体温), ) elderly models.ForeignKey(ElderlyProfile, on_deletemodels.CASCADE, related_namehealth_records) indicator models.CharField(max_length20, choicesINDICATOR_CHOICES) value models.CharField(max_length50, verbose_name测量值如120/80) measured_at models.DateTimeField(verbose_name测量时间) note models.CharField(max_length255, blankTrue) created_at models.DateTimeField(auto_now_addTrue) class WarningRule(models.Model): indicator models.CharField(max_length20, choicesHealthRecord.INDICATOR_CHOICES) operator models.CharField(max_length10, choices((gt, 大于), (lt, 小于), (range, 区间外))) threshold models.CharField(max_length50, verbose_name阈值如140/90) continue_times models.IntegerField(default1, verbose_name连续触发次数阈值) is_active models.BooleanField(defaultTrue) description models.CharField(max_length255, blankTrue) class WarningRecord(models.Model): STATUS_CHOICES ( (pending, 待处理), (confirmed, 已确认), (resolved, 已办结), ) elderly models.ForeignKey(ElderlyProfile, on_deletemodels.CASCADE, related_namewarning_records) rule models.ForeignKey(WarningRule, on_deletemodels.SET_NULL, nullTrue) record models.ForeignKey(HealthRecord, on_deletemodels.CASCADE) summary models.CharField(max_length255, verbose_name预警摘要) detail models.TextField(verbose_name预警详情) status models.CharField(max_length10, choicesSTATUS_CHOICES, defaultpending) confirmed_by models.ForeignKey(User, on_deletemodels.SET_NULL, nullTrue, blankTrue, related_nameconfirmed_warnings) confirmed_at models.DateTimeField(nullTrue, blankTrue) created_at models.DateTimeField(auto_now_addTrue)血压这种复合值建议存在字符字段里存储120/80这类格式判断的时候再解析成收缩压和舒张压分别判断。血糖、心率这类单值就直接用数字型但为了统一模型处理我依然用varchar存储判断时转float。这样做的缺点是查询不太方便优点是模型统一、方便扩展对于毕设项目来说是划算的。3.3 项目目录结构与分层思想Django项目我习惯按功能模块分app而不是把所有东西塞在同一个app里。推荐结构如下health_warning/ ├── manage.py ├── config/ # 项目配置目录 │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── apps/ │ ├── users/ # 用户与角色 │ ├── elderly/ # 老人档案 │ ├── health/ # 体征数据 │ ├── warning/ # 预警规则与预警记录 │ └── dashboard/ # 可视化与统计 ├── templates/ ├── static/ ├── scripts/ # 模拟数据、定时任务脚本 └── requirements.txt按照这个拆分职责清晰哪部分出问题直接进对应的app排查。你可以用命令行快速建好这些app然后把apps目录注册进settings再把每个app对应的URL路由写到config/urls.py里。我见过太多人把所有逻辑写在views.py里上千行代码一个文件后期改一个功能要滚半天答辩被老师问起代码结构时也说不清楚。4. 预警引擎的实现把判断逻辑做成可配置的规则系统4.1 为什么不能把阈值写死在视图里一句话写死的阈值只能骗得过演示骗不过答辩老师。如果你在views.py里写死一个判断if value 140老师大概率会追问那如果这个老人血压常年偏低120就算偏高呢如果我需要把预警阈值从140改成130是不是要改代码重新部署比如高龄老人和低龄老人的正常值范围本就应该不同你的系统怎么处理这种差异正确的做法是做一张预警规则表就是我上面设计的WarningRule让管理员在后台直接配置规则。这是一个很加分的点因为说明你考虑到了系统的实际可维护性而不是只写了个demo。4.2 规则评估逻辑支持连续次数与数值区间规则评估我单独封装了一个类放在warning/services.py里。核心思路是拿到一条健康记录后自动找到对应的规则解析阈值校准连续N次异常计数最终返回是否触发预警。from .models import WarningRule, WarningRecord def build_criteria(rule): return { operator: rule.operator, threshold: rule.threshold, } class WarningEvaluator: def __init__(self, elderly_id, indicator): self.elderly_id elderly_id self.indicator indicator def get_active_rule(self): return WarningRule.objects.filter( indicatorself.indicator, is_activeTrue ).first() def evaluate(self, value, measured_at): rule self.get_active_rule() if not rule: return None matched self._match(rule, value) if not matched: return None cnt self._count_continuous_abnormal(measured_at, rule.continue_times) if cnt rule.continue_times: return rule return None def _match(self, rule, value): # 按规则类型解析阈值和值返回布尔 if rule.indicator blood_pressure: return self._match_blood_pressure(rule, value) else: return self._match_single_value(rule, value) def _match_single_value(self, rule, value): val float(value) thr float(rule.threshold) if rule.operator gt: return val thr elif rule.operator lt: return val thr elif rule.operator range: # 阈值格式为下限,上限 low, high [float(x) for x in rule.threshold.split(,)] return val low or val high return False_count_continuous_abnormal的逻辑是查这个老人最近N次同一指标的记录如果这N条记录全部命中规则即都异常才返回N。这样设计是为了规避偶发性波动造成的误报比如老人刚刚爬完楼梯心率突然高一下马上又恢复正常没持续异常就不该报警。4.3 预警通知与状态闭环一旦规则命中我建议通过Django的Signal机制自动生成预警记录并推送站内通知。把通知逻辑解耦出来不在视图里直接调用这样不管数据将来从哪个渠道进来都能走同一套预警流程。# warning/signals.py from django.db.models.signals import post_save from django.dispatch import receiver from .models import WarningRecord, ElderlyProfile from .services import WarningEvaluator receiver(post_save, senderHealthRecord) def check_warning_on_record_save(sender, instance, created, **kwargs): if not created: return evaluator WarningEvaluator(instance.elderly_id, instance.indicator) rule evaluator.evaluate(instance.value, instance.measured_at) if rule: WarningRecord.objects.create( elderlyinstance.elderly, rulerule, recordinstance, summaryf{instance.get_indicator_display()}异常预警, detailf检测到{instance.indicator}持续异常当前值{instance.value}, )生成预警记录之后家属在预警中心列表里看到点击确认、填写处理备注、标记为已办结。预警列表默认按时间倒序、按状态过滤老记录自动折叠到历史列表里避免一次重复预警刷屏。如果有需要你还可以加一个24小时未处理预警的提醒角标这又是一个让老师眼前一亮的细节。5. 可视化与适老化前端交互让家属一眼看懂老人的状态5.1 图表组件选型ECharts依旧是首选数据可视化部分我强烈推荐ECharts原因有几个中文文档全、开箱即用、图表类型多而且不需要懂前端框架直接在Django模板里引入一个js文件就能跑。Chart.js也可以但它的联动交互和预警标记功能不如ECharts丰富。拿趋势图来说用一个折线图即可解决x轴是测量时间y轴是指标值再在图上画一条预警阈值线。老人血压一旦超过阈值线阈值线到折线之间的区域自动标红家属一眼就能看到哪里出问题。!-- templates/dashboard/trend.html 核心片段 -- div idtrendChart styleheight: 360px;/div script const chart echarts.init(document.getElementById(trendChart)); $.getJSON(/dashboard/api/trend/?elderly_id1, function(data) { chart.setOption({ title: { text: 近30天血压趋势 }, tooltip: { trigger: axis }, xAxis: { type: category, data: data.dates }, yAxis: { type: value, name: 血压(mmHg) }, series: [{ name: 收缩压, type: line, data: data.systolic, markLine: { data: [{ yAxis: 140, name: 预警阈值 }] }, markArea: { data: [[{ yAxis: 140 }, { yAxis: 200 }]] } }] }); }); /script5.2 适老化设计注意事项清单做前端的时候请把适老化落到每个具体细节答辩时直接指着页面向老师解释。这比空口说我考虑了适老化有说服力得多。字体大小基准16px以上重要数字用24px以上加粗展示。页面主色调用高对比度配色比如深蓝白色底预警用红色底白字不要太柔和以至于看不清。核心按钮做得大点击区域至少44×44像素。预警卡片用醒目的边框和背景色非预警的信息卡片统一弱化。每张图表下方放一句直接结论比如近一周血压整体平稳有1天偏高让看不懂图表的人也能获取结论。很多同学是功能做完了才想起设计结果就是页面元素全都挤在一起。你自己用手机打开看一下如果觉得手指不好点那老人就更难用了。5.3 Django与前端的数据对接模式我不建议在模板里直接循环输出一堆div然后CSS控制显示那样做图表联动和动态刷新会非常痛苦。推荐的做法是Django提供独立的JSON接口前端用Ajax取数配合ECharts渲染。# dashboard/views.py from django.http import JsonResponse from .models import HealthRecord from django.utils.timezone import now from datetime import timedelta def api_trend(request): elderly_id request.GET.get(elderly_id) days request.GET.get(days, 30) start_date now() - timedelta(daysint(days)) records HealthRecord.objects.filter( elderly_idelderly_id, indicatorblood_pressure, measured_at__gtestart_date, ).order_by(measured_at) dates, systolic, diastolic [], [], [] for r in records: try: sys_val, dia_val map(int, r.value.split(/)) except ValueError: continue dates.append(r.measured_at.strftime(%m-%d)) systolic.append(sys_val) diastolic.append(dia_val) return JsonResponse({dates: dates, systolic: systolic, diastolic: diastolic})这里顺带演示了Django ORM的查询操作比如按时间范围过滤、字段解析、结果序列化。答辩被问到怎么删除一条查询结果这类基础问题时你也可以说清楚filter().delete()的用法这些都是Django的常规操作属于必会内容。6. 我在开发中踩过的坑和完整排查过程6.1 坑一测量时间的时区问题导致趋势图错位现象是趋势图上的数据点全部往后偏移了8小时明明是下午录的数据图上却显示在凌晨。排查过程先在Django shell里直接查数据库发现created_at字段存的是UTC时间而浏览器展示用的是本地时间两者差了8小时。再检查settings.py发现TIME_ZONE没有设置成正确值。解决方式很直接TIME_ZONE Asia/Shanghai同时把USE_TZ True保持开启。录入表单的时候前端提交的时间字符串要按本地时区解析后端存储统一用UTC展示时Django模板会自动转回本地时区。这个坑几乎每个Django项目都会踩一次你踩过了反而能在答辩时聊聊时区设计的工程意义。6.2 坑二ORM关联查询的N1问题预警列表页最开始是这样写的循环每个预警记录然后warning.record取体征记录再warning.elderly取老人姓名。列表页一次加载50条记录结果SQL查询次数飙到150多次页面卡得明显。排查过程我在页面加载时打开Django Debug Toolbar看到SQL查询数量异常逐一数下来都是对关联对象的重复查询。解决方式查询预警列表时用select_related把外键关联的对象一次性取出来。warnings WarningRecord.objects.select_related(elderly, rule, record).filter(statuspending)改完之后SQL查询数从150降到了个位数。这个优化方式在任何Django项目里都是高频考点你可以在博文或者论文里把这个排查过程写进去属于很有说服力的项目亮点。6.3 坑三异常录入值导致的预警误报开发测试阶段我用脚本模拟数据结果脚本里不小心生成了一条血压300/200的记录系统立刻给所有家属发了预警邮件。实际上这条数据明显是无效的——血压不可能到300这类异常值应该被识别为录入错误而不是健康风险。排查过程我先在规则评估逻辑里加了一条打印发现它走的流程和正常异常值完全一致问题不在规则引擎而在数据入口。解决方式在健康数据录入表单和接口层做两层校验。第一层是基础范围校验比如收缩压只允许60到250之间超出直接提示重新录入第二层是录入时间校验同一老人同一指标同一测量时间的数据重复提交自动拒绝并提示该时间段已有记录。这两层校验做完误报率直接降到底。6.4 演示数据生成的小技巧毕设演示最怕的是页面上没有数据图表光秃秃一片。很多同学手动录入几十条数据录到崩溃其实完全可以用脚本批量生成。我当时写了一个scripts/generate_demo_data.py用random模块模拟一位老人30天的体征数据正常波动为主每隔几天穿插一次超阈值数据这样趋势图有起伏、预警记录有几条、统计图表也好看。生成脚本里注意把已办结和待处理的预警记录都留几条演示的时候直接给老师看状态流转不用现场录数据。import random from datetime import datetime, timedelta from apps.elderly.models import ElderlyProfile from apps.health.models import HealthRecord elderly ElderlyProfile.objects.get(id1) start datetime.now() - timedelta(days30) for i in range(30): measured_at start timedelta(daysi) systolic random.randint(118, 140) if i % 7 0: # 每周造一次临界异常 systolic random.randint(141, 155) HealthRecord.objects.create( elderlyelderly, indicatorblood_pressure, valuef{systolic}/{random.randint(75, 90)}, measured_atmeasured_at, )生成完记得跑一下预警信号让部分记录自动产生WarningRecord历史预警统计就出来了。7. 远程调试与答辩演示让项目在别人电脑上也能跑起来7.1 为什么远程调试是交付环节的刚需收到源码的同学最常见的问题是我本地跑不起来——环境不对、数据库版本不对、Python版本不对各种问题层出不穷。远程调试是解决这些问题最有效的手段。作为开发者或项目交付者你需要在对方电脑上或者你自己远程的一台干净机器上直接定位运行环境问题。调试Django时远程调试可以让你像本地开发一样打断点、查变量而不是靠日志一行行猜。7.2 VSCode Remote调试配置我实际调试这类项目时最常用的方式是用VSCode的Remote SSH连到服务器或另一台机器直接在远程环境里运行项目并调试。步骤很简单在VSCode安装Remote-SSH扩展。配置SSH连接信息把远程机器的IP和用户名填好。连接成功后打开远程目录安装Python扩展。在.vscode/launch.json里配置Django调试器。{ version: 0.2.0, configurations: [ { name: Django Remote Debug, type: python, request: attach, host: 0.0.0.0, port: 5678, pathMappings: [ { localRoot: ${workspaceFolder}, remoteRoot: /home/ubuntu/health_warning } ] } ] }配合项目里安装的debugpy在需要断点的代码位置打个标记然后在远程机器上启动项目在本地VSCode点击调试按钮就能远程断点跟踪代码。这个方法处理本机能跑、别人机器跑不了的问题最直观。7.3 Django局域网访问配置如果你是在教室/宿舍演示一台电脑跑服务另外一台电脑打开浏览器访问你需要做三件事在settings.py里把ALLOWED_HOSTS配置成[*]或者明确加上你机器的局域网IP。用python manage.py runserver 0.0.0.0:8000启动而不是默认的127.0.0.1。确保本机防火墙放行8000端口。这样同一局域网下的任何设备都能通过http://你的IP:8000访问项目。演示的时候最好准备两台设备一台跑后端一台用来展示避免老师盯着自己屏幕看代码的尴尬。7.4 部署方案取舍演示阶段不一定要上云很多同学一上来就想把项目部署到云服务器折腾域名、HTTPS、uWSGI结果部署花的时间比开发还多。我的建议是答辩前按这个优先级来本地跑通、局域网演示、有时间再考虑云部署。如果确实需要在云端演示最简单的组合是gunicorn nginx MySQL。Django处理动态请求nginx托管静态文件和转发请求。但这套需要你有一定的Linux基础我不建议在临近答辩才去折腾。我自己带项目时通常先把本地和局域网方案跑稳云部署只是一个加分项不是必需项。8. 往加分项方向扩展的几条思路8.1 对接硬件设备如果你的课题允许可以考虑加入设备数据自动采集模块。比如树莓派配合传感器或者一些支持API的智能手环把测量数据自动通过接口写入系统。哪怕只做一个模拟接口在论文里写清楚接入IoT设备后的数据流设计整个项目的高度都不一样了。8.2 预警推送从站内信扩展到微信/短信站内信预警的缺点是不够及时。你可以接入微信模板消息或短信服务预警触发时主动推送。这类第三方服务通常有免费测试额度功能本身也不复杂本质上就是在预警Signal里多调用一个发送函数。做好了项目的实用性和演示冲击力会明显提升。8.3 升级为健康趋势风险评分如果你学有余力可以在规则判定基础上做一个风险评分模块。比如根据近7天数据计算一个趋势系数血压持续走高则在分数上累加生成低风险/中风险/高风险等级展示给家属。这里不需要复杂的机器学习简单做一个加权评分算法就够扩展用了而且答辩时更好讲清楚数学原理。8.4 我的一点实际体会这个题目如果能静下心做完你收获的绝不仅仅是一份源码。你会把用户角色、业务流程、数据库设计、规则引擎、数据可视化、部署调试这一整条链路完整走过一遍。我自己带项目时最深的感受是这个题目的核心难点不在某个单独的技术点上而在把所有环节串起来的时候每一步都可能碰到小问题而解决这些小问题的过程恰恰就是你答辩时最有底气讲出来的部分。如果让我给一条最实在的建议那就是不要追求功能多把一个点到做透。比如把预警闭环做到状态流转完整、页面展示清晰、规则配置灵活就已经是一个非常优秀的毕业设计了。剩下的时间好好准备演示环境比再加一个功能重要得多。