脊柱外科病人资料管理系统的界面设计分析(2)--JOA评分记录的实现
在上篇随笔《脊柱外科病人资料管理系统的界面设计分析》中介绍了一些常用的界面设计方面的内容,本篇继续上一篇,介绍脊柱外科病人管理系统的JOA评分记录模块的界面设计以及实现方面的内容。
JOA(全称 Japanese Orthopaedic Association Scores for Assessment of Cervical Myelopathy),日本骨科学会(JOA)颈椎病疗效评定标准,用于在脊柱外科的术前术后,对患者身体状况进行量化,并制定相关的护理方案提供依据。JOA评分记录模块,是软件《脊柱外科病人资料管理系统》的一个亮点,能使外科医生或者护士,对患者的信息进行全面的记录和研究参考。
1、JOA评分记录模块的分析
JOA评分记录,有点类似于考题的方式,对各项内容进行分值的评估,每项记录的得分不同,汇总成一个总的得分,用于量化评估,它的分类大致如下所示。
从上面的文档截图可以看到,评分项目可以分为一个大类(如自觉症状),多个子项目(如下腰痛)这样的组织方式,然后我们需要记录每项的得分,以及所有项目累加的总分。
通过分拆,我们可以把一个记分的题目作为一个控件,每个题目它自己的得分明细可以动态从数据库获取即可,界面控件设计如下所示。
通过上面的分析,我们知道,一个项目大类(如自觉症状)包含了多个子项目(如下腰痛、步态等)这样的题目,也就是多个上面控件的实例,那么我们设计的项目大类控件界面如下所示。
以上的界面,其实就是在一个大的项目大类控件上组合多个子项目控件的效果。
然后,整个JOA评分的界面就是多个上面项目大类的组合了,组合成了一个JOA评分记录模块的控件效果,如下所示。
最后,我们在第一个文档截图里面看到,JOA评分分为两个方面,一个是术前的,一个是术后的,他们的评分界面完全一样,那么我们可以把它们用两个Tab界面进行分开处理,最后得到的运行界面如下所示。
2、JOA评分记录的逻辑实现
为了在界面呈现各项分数项目,我们需要在数据库设计一个表JOAItem,用来存储每个评分项目的内容,然后在界面中根据分类进行动态展示。
然后定义一个评分子项目的信息对象ControlItem,作为上面控件的信息对象,方便控件和数据库关联起来,记分或者存储明细到数据库中,代码如下所示。
/// <summary>
/// JOA评分项目明细
/// </summary>
[DataContract]
public class ControlItem
{
/// <summary>
/// 序号,从1开始
/// </summary>
[DataMember]
public virtual int Seq { get; set; } /// <summary>
/// 分类名称
/// </summary>
[DataMember]
public virtual string Category { get; set; } /// <summary>
/// 项目明细列表(包括项目得分等信息)
/// </summary>
[DataMember]
public virtual List<JOAItemInfo> ItemList { get; set; } /// <summary>
/// 评分项目第一项得分(默认得分)
/// </summary>
public virtual decimal DefaultScore
{
get
{
if (ItemList == null || ItemList.Count == )
{
return 0M;
}
else
{
return ItemList[].Score;
}
}
} /// <summary>
/// 默认构造函数
/// </summary>
public ControlItem()
{
ItemList = new List<JOAItemInfo>();
} /// <summary>
/// 参数构造函数
/// </summary>
/// <param name="seq">序号</param>
/// <param name="category">分类名称</param>
/// <param name="itemList">项目明细列表</param>
public ControlItem(int seq, string category, List<JOAItemInfo> itemList) : this()
{
this.Seq = seq;
this.Category = category;
this.ItemList = itemList;
}
}
在上面的评分控件中,我们整合以上的信息对象作为一个整体,部分代码如下所示。
public partial class ScoreItemControl : DevExpress.XtraEditors.XtraUserControl
{
/// <summary>
/// 单项的序号,从1开始
/// </summary>
public int Seq = ; /// <summary>
/// 控件绑定的信息
/// </summary>
public ControlItem ControlItem { get;set; } /// <summary>
/// 单项的得分
/// </summary>
public decimal Score { get; set; } /// <summary>
/// 处理分数变化后的事件触发
/// </summary>
public event ScoreChangedHandler OnScoreChanged; ............................
当我们在评分控件中指定了ControlItem信息后,在控件的Load事件里面,将会动态绑定评分的项目明细,代码如下所示。
private void ScoreItemControl_Load(object sender, EventArgs e)
{
if (ControlItem != null && !this.DesignMode)
{
this.lblItemIndex.Text = ControlItem.Seq.ToString();
this.layoutItem.Text = ControlItem.Category; List<CListItem> itemList = new List<CListItem>();
foreach (JOAItemInfo info in ControlItem.ItemList)
{
itemList.Add(new CListItem(info.ItemDetail, info.Score.ToString()));
} radItemGroup.BindDictItems(itemList);
} if (radItemGroup.Properties.Items.Count > )
{
this.radItemGroup.SelectedIndex = ;
}
}
除了ControlItem信息对象的绑定,我们还注意到上面的OnScoreChanged事件,它就是为了我们在整个控件中实现分数动态变化的一个事件,这样我们变化任何一个评分项目信息,单项分数和总分都会重新计算一次的事件。
/// <summary>
/// 处理分数变化后的事件触发
/// </summary>
public virtual void ProcessScoreChanged(int seq, decimal score)
{
if (OnScoreChanged != null)
{
OnScoreChanged(seq, score);
}
} private void radItemGroup_SelectedIndexChanged(object sender, EventArgs e)
{
this.lblItemScore.Text = string.Format("得分({0})分", this.radItemGroup.EditValue); decimal result = ;
if (decimal.TryParse(this.radItemGroup.EditValue.ToString(), out result))
{
this.Score = result;
ProcessScoreChanged(Seq, result);
}
}
以上代码逻辑就是最小评分控件的一个具体的实现,完成以上这些,还需要完成一个评分项目大类的具体逻辑,它的操作方式和上面差不多,也是引入一个信息对象集合作为背后得分计算的逻辑。
定义的信息对象ProjectItem代码如下所示。
/// <summary>
/// JOA评分项目信息
/// </summary>
[DataContract]
public class ProjectItem
{
/// <summary>
/// 序号,从1开始
/// </summary>
[DataMember]
public virtual int Seq { get; set; } /// <summary>
/// 项目名称
/// </summary>
[DataMember]
public virtual string Project { get; set; } /// <summary>
/// 项目明细列表
/// </summary>
[DataMember]
public virtual List<ControlItem> ItemList { get; set; } /// <summary>
/// 默认构造函数
/// </summary>
public ProjectItem()
{
ItemList = new List<ControlItem>();
} /// <summary>
/// 评分项目第一项得分总和(默认得分)
/// </summary>
public virtual decimal DefaultScore
{
get
{
if (ItemList == null || ItemList.Count == )
{
return 0M;
}
else
{
decimal total = 0M;
foreach (ControlItem item in ItemList)
{
total += item.DefaultScore;
}
return total;
}
}
} /// <summary>
/// 参数化构造函数
/// </summary>
/// <param name="seq"></param>
/// <param name="project"></param>
/// <param name="itemList"></param>
public ProjectItem(int seq, string project, List<ControlItem> itemList) : this()
{
this.Seq = seq;
this.Project = project;
this.ItemList = itemList;
}
}
然后该控件的逻辑代码就是结合这个信息对象以及控件的一些事件进行处理了,控件的部分代码如下所示。
public partial class ScoreProjectControl : DevExpress.XtraEditors.XtraUserControl
{
/// <summary>
/// 项目大类的序号,从1开始
/// </summary>
public int ProjectSeq = ; /// <summary>
/// 项目大类的信息
/// </summary>
public ProjectItem ProjectItem { get; set; } /// <summary>
/// 处理分数变化后的事件触发
/// </summary>
public event ScoreChangedHandler OnScoreChanged; private Dictionary<int, decimal> scoreList = new Dictionary<int, decimal>();//记录单项的得分列表 ...................
由于每项评分子项目是单独的评分控件,控件的布局采用了FlowLayout布局呈现方式,因此在控件的Load事件代码如下所示。
private void ScoreProjectControl_Load(object sender, EventArgs e)
{
if (ProjectItem != null && !this.DesignMode)
{
this.lblProject.Text = string.Format("{0}、{1}", ProjectItem.Seq, ProjectItem.Project); this.flowLayoutPanel1.Controls.Clear();
int index = ;
foreach (ControlItem item in ProjectItem.ItemList)
{
ScoreItemControl control = new ScoreItemControl();
control.ControlItem = item;
control.Seq = index++;
control.OnScoreChanged += new ScoreChangedHandler(control_OnScoreChanged);
this.flowLayoutPanel1.Controls.Add(control);
}
}
}
同样整个控件也有一个OnScoreChanged 的事件,我们看到,这个和上面介绍的事件操作方式类似,都是一级负责一级的分数处理,具体代码如下所示。
void control_OnScoreChanged(int seq, decimal score)
{
if(!scoreList.ContainsKey(seq))
{
scoreList.Add(seq, score);
}
else
{
scoreList[seq] = score;
} //项目的总分变化
ProcessScoreChanged(ProjectSeq, this.TotalScores);
}
以上的控件实现逻辑一步步递推,就能很好实现评分项目的动态呈现,以及控件评分分数的动态变化和总分记录保存,由于涉及的实现细节还比较多,一篇随笔介绍内容太多显得累赘,但是其他控件的实现逻辑和上面的操作方式差不多,在这里就不在一一赘述了,本文主要提供一个这种的实现思路进行JOA评分记录模块的实现,进一步拓展,可以把它应用到考试题目上 ,可以作为动态抽取题目,然后记录测试者的题目选择信息,最后把测试者的答案和标准答案对比得出用户的总分,这样就完成了试题的动态测试案例了。
脊柱外科病人资料管理系统的界面设计分析(2)--JOA评分记录的实现的更多相关文章
- HTML5+规范:nativeUI(管理系统原生界面)
nativeUI管理系统原生界面,可用于弹出系统原生提示对话框窗口.时间日期选择对话框.等待对话框等. 1.方法 1.1.actionSheet: 弹出系统选择按钮框 void plus.native ...
- WPF软件开发系统之四——医疗病人信息管理系统
仿360悬浮窗的方式,始终有个工具栏浮在桌面的最顶层,方便任何时候操作. 主要功能包括:病人信息的添加.修改.查询.包括别人基本信息.诊断结果.接待医生.手术多张图片等. 系统特点:简洁.易操作.美观 ...
- Qt编写气体安全管理系统(界面超漂亮)
自从把Qt样式表葵花宝典这个pdf文件看完以后,将所有的qss内容都轮了一遍,还写了个皮肤生成器工具,https://blog.csdn.net/feiyangqingyun/article/deta ...
- 在EF的code frist下写稳健的权限管理系统:界面设计(四)
基本都是采用pure设计(中文官网:http://purecss.org,英文官网:http://purecss.io).pure只是一个简单强大的cssUI库,支持响应式设计,适合自己设计或者给美工 ...
- 黑色的网站后台管理系统ui界面——后台
链接:http://pan.baidu.com/s/1pLffwE3 密码:m4v6
- Docker集中化web界面管理平台-Shipyard部署记录
Docker图形页面管理工具基本常用的有三种: DOCKER UI,Shipyard,Portainer.对比后发现,Shipyard最强大,其次是Portainer,最后是Docker ui.之前介 ...
- Django项目:CRM(客户关系管理系统)--68--58PerfectCRM实现king_admin批量生成上课记录
# kingadmin.py # ————————04PerfectCRM实现King_admin注册功能———————— from crm import models #print("ki ...
- Django项目:CRM(客户关系管理系统)--67--57PerfectCRM实现admin批量生成上课记录
#admin.py # ————————01PerfectCRM基本配置ADMIN———————— from django.contrib import admin # Register your m ...
- Winform开发框架之通用高级查询模块
最近一直忙于公司的事情,虽然一直在做一些相关的技术研究,但是很久没能静下心来好好写写博客文章了,想想也有半个月之多了,这半个月来,也一直致力于改善我的WInform开发框架,使得自己及客户使用起来更加 ...
随机推荐
- 你可能不知道的python
1.如何循环获得下标,使用 enumerate ints = ['a','b','c','d','e','f'] for idx, val in enumerate(ints): print idx, ...
- leveldb - sstable格式
整体上,sstable文件分为数据区与索引区,尾部的footer指出了meta index block与data index block的偏移与大小,data index block指出了各data ...
- LINQ TO ENTITY 根据Birthday获取Age
from emp in EmployeeInfo let years = EntityFunctions.DiffYears(emp.Birthday.Value,DateTime.Now) let ...
- C#调用JAVA接口WSSE方式用WebClient方式
C#读取JAVA的WSSE接口的调用代码: 用webclient 方式: /// <summary> /// 调用java cxf ws_security加密的服务wcf客户端对应的加密类 ...
- VS2013 解决方案文件结构分析
http://www.cnblogs.com/haogj/p/4248030.html Visual Studio 的解决方案文件是一个文本文件,其中的内容不是太复杂,有些时候 Visual Stud ...
- 【总结】编写自己的JDBC框架
一.数据库连接池: 在一般用JDBC 进行连接数据库进行CRUD操作时,每一次都会: 通过:java.sql.Connection conn = DriverManager.getConnection ...
- ALTER SEQUENCE 修改序列解决唯一约束冲突 unique constraint violated
背景 自增序列会遇到也会遇到唯一约束冲突吗?是的,最常见的情况就是数据迁移之后,导致数据最大值超过序列值. 软件开发中不遇到些出乎意料的问题,总感觉不太够劲. 修改序列(ALTER SEQUENCE) ...
- Spark和hadoop的关系
1. Spark VSHadoop有哪些异同点? Hadoop:分布式批处理计算,强调批处理,常用于数据挖掘和数据分析. Spark:是一个基于内存计算的开源的集群计算系统,目的是让数据分析更加快速, ...
- 给animator动态添加事件
using UnityEngine; using System.Collections; public class setAnimationEvent : MonoBehaviour { public ...
- 使用NSKeyedArchiver归档
将各种类型的对象存储到文件中,而不仅仅是字符串.数组和字典类型,有一种更灵活的方法.就是利用NSKeyedAarchiver类创建带键(keyed)的档案来完成. Mac OS X从版本10.2开始支 ...