sdu软件学院创新实训 个人博客6

前言

在本阶段的创新实训项目开发中,我主要完成了“患儿既往史健康档案仓”这一功能模块的设计与实现。该模块功能主要存放在pages/2_medical_history.py,其目标并不是单纯新增一个表单页,而是让系统具备既往史信息的结构化录入、档案化展示、物理删除以及普通登录用户可自主维护 的完整能力。

这一阶段的工作重点,是把原本分散、一次性的病史信息整理成一个可查看、可管理、可复用、可与账户绑定的健康档案仓,为后续智能预诊提供更加稳定的前置医疗信息支撑。

本阶段的主要功能实现

1. 登录门控与权限下放

我在做这个模块时,首先处理的不是表单,而是权限边界。因为既往史属于敏感健康信息,如果页面能被未登录用户直接访问,那么后续所有功能都失去了意义。所以我在pages/2_medical_history.py中,优先通过st.session_state.get("logged_in")判断用户是否已登录,如果未登录,就直接提示并跳转回主页面,同时调用st.stop()终止后续的渲染。

在完成基础门控之后,我进一步把这一功能模块从偏管理员控制的逻辑中释放出来,真正实现了 权限下放。这里的下放并不是让所有人都能看所有数据,而是让普通登录用户也能自主维护自己的既往史档案。因此我在页面中使用:

current_user = st.session_state.user

并将新增、查询、删除操作全部与current_user["id"]绑定。这样一来:

  • 登录用户可以进入既往史页面;
  • 每个用户只能读取自己账户下的病史档案;
  • 每个用户也只能操作属于自己的记录。

这个功能的作用非常直接,它让系统从“后台可维护”变成了“前台可自助”,同时又保证了数据隔离,是我这一阶段在业务权限设计上的一个关键改进。

2. 结构化表单录入

在完成访问控制之后,我又实现了既往史的录入功能。过去病史信息如果只是零散地写在对话里,不仅不方便复用,也不利于后续分析。所以我在这个阶段把病史录入做成了一个正式的结构化表单,让它真正具备“建档”的意义。

具体实现时,我使用了 Streamlit 的:

with st.form("medical_history_form", clear_on_submit=True):

把整套录入流程封装进同一个表单中。这样用户只有点击提交按钮时,系统才会统一处理表单内容,避免输入过程中因为页面实时重跑而打断录入体验。表单中我主要设置了以下字段:

  • 患儿姓名/昵称
  • 确诊疾病名称
  • 医院确诊/就诊日期
  • 就诊确诊医院
  • 治疗方案/用药说明
  • 备注信息

其中,确诊疾病名称是我设置的核心必填项,因为它决定了这条档案最基本的医学含义;而医院、治疗方案、备注等字段允许为空,但会在提交前做兜底处理,避免写入数据库后出现结构不完整的问题。

3. 数据落盘与接口封装

如果只有前端表单而没有后端落盘,那么“健康档案仓”依然只是一个界面概念。因此在录入功能完成后,我继续补齐了数据层逻辑,把既往史信息正式写入数据库。

在实现方式上,我没有把 SQL 直接写进页面文件,而是把与既往史相关的操作统一封装到app/db/models.py中,分别提供了:

  • create_medical_history(...)
  • get_medical_history_by_user(...)
  • delete_medical_history(...)

与此同时,我在app/db/database.py中新增了medical_history表,用于存储患儿既往史相关信息,主要字段包括:

  • user_id
  • child_name
  • disease_name
  • diagnosed_date
  • hospital
  • treatment
  • notes

为了让按账户查询更加高效,我还为user_id建立了索引。这样设计之后,页面层负责收集输入和反馈结果,数据层负责真正的持久化操作,整个模块的职责边界就比较清晰。

4. 既往史卡片展示

在有了数据之后,我接着实现的是既往史档案的查看功能。这里我没有采用简单的字段直出,而是选择通过容器循环渲染的方式,把每条病史档案做成独立卡片。

页面中我先调用了

histories = get_medical_history_by_user(current_user["id"])

获取当前账户下的全部既往史记录,再逐条生成卡片式内容。卡片中我对信息做了分层处理:

  • 标题层展示确诊疾病和患儿姓名;
  • 元信息层展示确诊日期和医院;
  • 正文层展示治疗方案与备注说明。

为了提升页面可读性,我还通过st.markdown(..., unsafe_allow_html=True)注入了自定义 CSS,对卡片的圆角、边框、阴影、留白、字体层级和浅色背景进行了统一设计。这样做的原因很简单:既往史数据本身信息密度高,如果直接用原始列表堆出来,用户阅读时会很累;而卡片式展示更适合医疗档案这种需要快速扫读和核对的业务场景。

5. 物理删除与动态刷新

既往史档案一旦进入系统,就必须允许用户在录入错误、重复提交或信息失效时进行纠正。因此在这一阶段,我还完成了删除功能,并且把删除后的页面刷新一起打通,形成了完整闭环。

具体来说,我为每一条既往史卡片都配置了独立的删除按钮。用户点击后,系统会调用:

delete_medical_history(h["id"])

对对应记录进行物理删除。删除成功后,我进一步执行:

st.rerun()

这样页面会立即重跑并重新加载最新数据,用户可以立刻看到删除后的结果,而不会出现“数据删了但界面还停留在原状态”的问题。

这个功能的作用不仅仅是“提供删除按钮”,更重要的是实现了错误数据可回收、前端视图可同步、交互结果可即时确认。对一个健康档案类模块来说,这种一致性是非常重要的。

总结

总体来说,这一阶段我主要完成了一个围绕患儿既往史信息展开的小型健康档案仓模块。将页面交互、权限控制、数据库落盘、卡片展示与动态刷新几部分工作的内容打通,形成了较完整的阶段性成果。

在后续迭代中,我准备继续围绕该模块做进一步完善,主要方向包括:补充真正的修改功能、增强结构化程度、补充筛选与检索能力。