碎片数据收集利器-结构化动态表单设计思路

本文基于面向基本公共卫生的业务系统设计经验,抽象出一套适合大型ERP系统的表单业务数据模型,目标是最大限度保留系统弹性的同时,尽可能降低系统复杂度和开发成本。enjoy~

背景

填写表单应该是所有业务线条中最避免不了的环节,例如我所经历的医疗项目:

居民健康档案
居民健康档案信息卡

以上面两个例图作为示例,可以看到姓名、性别、出生日期、血型等字段是完全重复的,由于业务场景的差异,表单被定义了不同的样式和字段结构,此时将遭遇以下几种问题:

  • 同一用户经历了两个不同场景时,不得不重复填写相同的字段;
  • 如果相同的字段在两个表格中的值不同,基本无法判断哪个为正确值,例如同一个人在居民健康档案中血型填写为A型,而在居民健康档案信息卡中填写为B型;
  • 某些字段会重复出现在不同的表单中,随着业务需要,将其串连起来查看其趋势,如身高、体重、血压、心率等等,以帮助医生确诊疾病,然而这些字段保存在各自的表单中,由于开发人员的变更、文档的遗漏和产品的迭代,无法穷举出所有的这些字段数据来源,即便能够回溯所有的来源,本身也是一件十分消耗精力的事情;
  • 因为政策或业务需要,要在原有的表单上做调整,新的标准导致表单字段产生变化,此时原有系统为保证其运行的稳定,难以从数据表和底层代码中迭代,只能新增数据表做开发,当表单需求频繁变化时,加剧数据碎片化的问题;
  • 新增业务表单时,开发需要订排期,用户需要等待发版后才能使用,新增大量表单时影响原有开发计划的同时,业务部门也难以快速开展系统业务。
  • 做数据统计和分析时,由迭代造成的数据字段遗失或变更,无法统计出完整而准确的数据,做出的报告难以反映出真实的情况
    ....

传统的区域化基本公共卫生系统正在经历这样的剧痛,当然其他行业比如金融的部分业务同样面临相同问题(本人只经历过这两个行业,见谅),如何在纷繁复杂的业务环节中抽离出四两拨千斤的数据模型,除了满足日益频繁的业务调整外,还能将数据完整的、标准的存储并利用起来,是后端产品经理的安身立命之本。作为一个不务正业的产品经理,这次就从数据库表结构设计上,介绍一套解决方案:结构化动态表单

场景和需求:

1.可覆盖绝大部分表单业务场景。
2.表单样式和字段可灵活调整,不影响历史积累数据,不会造成数据库和代码层面的频繁变更;
3.数据统计时能够快捷准确全面地获取到想要的字段数据,不过度依赖文档和程序员老员工;

模块介绍

模块划分

属性库

所有表单中所有的字段都在属性库中定义,相当于表单字段的字典。定义的核心包含属性的唯一标识、属性名、属性值取值规则和约束等信息。

因为我认为所有的字段都是围绕某个业务进行的,把这个业务抽象成对象,那么这些表单的字段就是这个对象的属性,所以命名为属性库

如果用关系型数据库表达属性库,根据以往的经验可以总结出如下两个基础表:


属性库表结构

属性分类,主要根据使用者需求对属性进行分类,方便查找和后期的批量数据统计,比如健康管理把心率、瞳孔大小、脉搏等属性规划到生命体征类,把身高、体重等属性规划到基本体征类等等,因此仅需要定义唯一识别码、名称和分类说明即可。

属性,这个表非常重要,是数据标准化的基础表。唯一标识、名称、说明,这是一个属性最基础的说明,不用解释。

  • 分类ID字段可支持多个ID,表示一个属性可划分到多个分类下,这个可根据实际需求定义,我所经历的场景是有这种情况的,比如心率,既可以是生命体征类属性,也可以是临床诊断类属性,很难绝对界定。当然属性和属性分类也可以通过单独建关系表来定义对应关系,方法有很多,各有优劣,看技术leader自行选型吧。

  • 属性类型,根据个人的经验,总结出图中的几种类型,相信大家都认识,不用展开,其中单选框、多选框两种类型因为还依赖对应的取值字典,因此还需要到属性值字典中定义取值选项。另外值单位这个字段,方便做数据转换和终端数据展示用,比如时长的值60,单位是分钟,通过算法即可转换该单位的值为1小时。

属性值字典,主要用于配合属性类型为单选框或多选框的取值,也是数据标准化的一部分。

例如定义一个属性叫性别的属性规划到基础信息分类中,此时会属性库的三个表中分别插入以下数据:
属性分类表:ID=‘1’,分类名称=‘基础信息’,分类说明=‘用户基本信息’
属性表:ID=2,分类ID=‘’,属性名称=‘性别’,属性说明=‘用户的性别’,属性类型=‘单选下拉框’,值单位=空
属性值字典:[ID=3,属性ID=‘2’,字典值=‘男’],[ID=4,属性ID=‘2’,字典值=‘女’],[ID=5,属性ID=‘2’,字典值=‘未知’]

模版库

所有的动态表单都是以模版的方式保存在数据库中,表单模版中定义表单中填写的字段、字段的默认值和表单样式。

由于表单样式的不可预见性,因此可以准备一套符合自家产品风格的视觉设计语言,限定表单视觉样式的框架,包含前面提到的属性类型呈现样式,和细化到UI在手写、PC端、移动端的字体大小、线条风格、交互方式、间距、缩进、比例、布局方式等参数,当然本篇由于篇幅限制不展开和视觉风格相关的讨论,读者可自行脑补。

既然是模版,肯定少不了控件,模版由控件组成,在这里把控件分为两类:属性组件和容器组件。

表单模版库表结构

表单模版,是表单的字典表,用于定义表单的基础信息如名称、用途说明等,如果与业务衔接,还可以添加关联的业务、填写对象、触发填写的时间等,这部分信息由具体的业务场景决定,可根据实际需求设置字段。

容器组件,负责定义外观样式的组件,决定了属性组件在表单中的呈现样式,可根据不同布局需求细分更多容器组件,这里不展开细讲。

  • 顺序号,在同级下的显示排序,从左至右,从上至下的原则进行排列。

  • 容器名称,即表单中某方框的名称,可不填

  • 在终端显示表单时,需要充分考虑各个组件在页面上的默认布局参数和可变参数。通常前面提到的设计语言中会定义标准的内边距外边距、线粗和线色等视觉样式,这些就是默认布局参数,但组件在表单中的显示顺序、嵌套关系和组件内的组件排列方式等参数多数时候是需要配置的,依据实际需求添加参数即可。

  • 容器组件可嵌套,当遭遇多级层级关系时,用容器组件实现嵌套关系再好不过了,不建议属性组件也支持嵌套,因为会提高属性值的取值复杂度,除了开发和数据存储逻辑复杂度高外,后期数据分析时也会进入逻辑黑洞,应尽量避免

  • 是否支持累加数据,此字段用于控制组件内的元素,是否可以按照定义的字段多组生成,例如如:

    多套数据的支持

    在容器组件主要用药情况中,属性组件药物名称用法用量用药时间服药依从性的值可以添加多次

  • 还可以添加跟多字段或子表,描述容器更多的视觉布局样式,比如支持PC端、移动端、打印手写的样式定义。

属性组件,来自于属性库中的属性,决定了表单中填写的字段信息。

  • 容器ID,当前属性组件放置在某个容器组件内,若值为null,表示直接放置在表单中

  • 属性别名,为适应部分个性化的需求,可以为属性定义别名,比如身高,对婴儿通常叫身长,对青少年或成年人叫身高。别名定义到模版中而不是在属性库的意义在于,用户的个性化称呼通常只会在自己所处的场景内使用,对于其他场景下的其他用户并不一定通用。

  • 属性默认值,很好理解,没用把这个字段放到属性库的理由和别名一样,场景不同,默认值不一定通用。

  • 是否必填,表单提交前判断必填项的依据。

  • 页面区域,用于判断当前组件出现在其父组件的位置,枚举类型。

属性组件还可以有更多可扩展特性,后面会提到一些。

业务数据库

有了前面的属性库和表单模版库的配置,即可配置出各式各样的表单,而实际使用这些表单保存下来的数据格式是怎样的呢?

业务数据库表结构

表单主表,作为表单的索引表,主要是提供表单的填写来源、时间戳和与业务相关的标记。

  • 通常实际业务有很多附加的信息,图中给出的是本人面临的业务场景常见的字段。

容器明细表,这里保存了表单内负责样式的容器数据,因为表单模版可能会变更,因此需要将其视觉样式数据保存下来,以记录当时呈现的样式,避免因为模版变更而造成的布局样式丢失。

属性明细表,保存了所有表单的所有字段的值。

  • 为了配合容器组件记录其布局样式,还添加了容器ID、顺序号、组号、页面区域,用于记录保存表单时属性在表单中的位置。

  • 组号,当遇到属性组件放置在允许累加数据的容器组件中时,标记出属性值所在的组。

  • 别名,若属性在模版中配置了别名,则保存在这里,如果值为空,则显示原属性名。

  • 修改时间,表单可能会遇到修改部分数据,因此标记字段的最后修改时间。如果有属性值的操作日志,可以不要。

样例

动态表单样例

弊端

  • 动态表单的存在,在一定程度上可以缓解产品迭代因业务变更带来的压力,但其开发复杂度较高,尤其表单模版,解析模版数据呈现到终端时,依赖遍历算法,对程序员的要求不低,若整套产品的应用规模不大,不建议使用动态表单,或者根据需求开发简配版。

  • 由于表单依赖属性库和表单模版的配置,属性和表单模版的维护质量决定了表单的数据质量,因此需要有高度责任心和专业能力的人员来进行属性库的维护,提高了使用门槛,但反过来讲,罗马不是一天建成的,如果有野心建立行业标准,本身也需要大力投入数据质控。

设计思想和基本原则

  • 产品开发和业务运行尽可能的解耦。业务人员不必完全依赖产品业务功能的情况下才能运行相关业务(这个问题单独靠动态表单无法完全解决,还需要依赖工作流,不过没有工作流也可以勉强适应部分场景做业务试运行);

  • 产品永远做功能迭代,尽量避免数据迭代。常见的C端产品往往会有很多的营销推广广告页,这些广告页常常会频繁变化,而且为了抓热点往往需要即时响应跟进,如果按照每周发版1-2次的节奏,等发出来商业机会已经凉了,因此往往会做一个后台配置广告页的功能,使运营人员可以自行配置广告页面,包含页面元素、入口布局、外链引导、渠道埋点配置等等,这就是功能迭代。如果运营改一次广告,产品即发一次版,这就是数据层迭代。每一次变更都将累积相应的数据,产品是生成这些数据的工具,产生数据是业务人员做的事情,产品和业务是冰淇淋机和卖冰淇淋的小姐姐的关系。

  • 用户永远只能看到功能,只关心产品是否满足其需求,而产品经理永远要从高低远近多维视角看待和解构需求,不断的整合、重组、拆分、归纳,穷举各种场景下的业务形态,在业务耦合和模块化处理上达到平衡,本质上是优化效率,创造利润,如果达不到这两个目的,这个产品不能叫产品,只叫艺术品。

  • 提前预判功能模块的发展趋势,在设计初期预留充分的扩展性和迭代方向,避免高频率的推倒重来,当然如果是敏捷开发,请无视这条。

意义

  • 属性库即数据规范,如果数据量在行业中足够大,适用面足够广的情况下,具备发展为行业规范的潜力。
  • 表单模版即数据接口标准,当多个系统需要进行数据对接时,最头疼的往往是梳理数据对接标准,将需要对接的数据模版通过接口规范的方式导出给对接方,数据字段和取值规范一目了然,新老系统导数据也会用到。
  • 数据利用更加便捷方便,需要查询某项具体的属性数据时,只需到属性明细表中即可找到,无需遍历其他业务表单
  • 用户可通过配置表单明确新需求,表单模版一定程度上提高了用户需求和功能落地的沟通效率,一定程度上提高了产品的业务可扩展性

扩展性

以下是随意举例的可能的功能扩展方向,仅作为扩展阅读

属性组件功能扩展

多属性之间的逻辑约束和默认值

  • 性别为男时,诊断中不可出现妇科疾病
  • 年龄在18-21岁之间,职业默认值为大学生
  • 填写了身份证号码即可解析出籍贯、性别和出生日期

单属性复用

  • 姓名性别等字段用户一旦填写后,以后再次填写有这些字段的表单即可自动填写

属性值字典
诊断、症状字典数据可能依赖外部接口调取,而非本地属性值字典库

容器组件扩展

  • 可配置容器背景图,视觉优化
  • 内部元素排列方式支持左对齐、右对齐、垂直排列、水平排列等
  • 可套用整体视觉设计的皮肤

模版库扩展

  • 模版插入公用参数字段,如表单中的制表机构、填表人、所在科室等等
  • 表单中的字段可作为工作流业务环节控制字段,比如当支付方式为现金时,无需弹出支付二维码

操作日志

  • 记录所有用户在业务表单上的操作记录,包含操作人、时间戳、修改前属性值
  • 记录所有用户在属性库和表单模版库上的操作记录
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 31,894评论 2 89
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,406评论 1 45
  • 摘录: 蓝色说话喜欢留有余地,而红色,很容易说满,等到出了问题,连补救的话也没了。 红色欠缺思考、重在当下、不留余...
    壹颗大橙子阅读 156评论 0 0
  • 《论语·为政》:子曰:“学而不思则罔,思而不学则殆。”只是学习却不思考就会迷惑而无所得,只是思考却不学习就会精神疲...
    a242022b9660阅读 510评论 0 0
  • 今天是宝贝入小学的第一个教师节,从昨晚宝贝就说要买花送给老师,早晨醒来宝贝让我绕路到天悦华府南门,说是以前看到那里...
    小茹妈妈阅读 139评论 0 1