网页表单文档设计及技术实现

在很多业务流程应用中,业务审批单的样式、内容多变,然而系统对业务表单数据并不敏感,因此,不使用对应的关系型数据表,而采用NoSQL技术来优化设计。因为NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。按NoSQL的特性,可以灵活进行schema结构(列定义)的修改,理论上应该可以很好支持这些多样表单的持久化保存。基于上述原因,业务审批单采用网页表单文档设计。

网页表单设计

首先,我们看一看在HTML表单元素(对象)中使用自定义属性的示例:

<input fieldid="name" fieldtype="char" size=50>名称</input><br>
通过自定义属性“fieldtype”来定义数据类型。<br>
<input fieldid="old" fieldtype="number" size=20 value="42">年龄</input><br>

网页表单数据字段定义

为了避免浏览器兼容性问题,通过自定义属性的方式来定义表单文档数据项,定义规则如下:

属性名称 作用说明 备注
fieldid 数据字段名称 避免与id冲突,单独命名
fieldtype 数据字段类型 支持主流number、text、datetime等
fieldsize 字段长度 主要是定义number、text等长度
fieldname 字段名称 定义中文名称
subtable 子表的列数 适用于嵌套多行子表结构,在table控件中定义
subid 子表的列名定义 适用于嵌套多行子表结构

对应JSON数据格式如下:

{数据字段名称1:value1,数据字段名称2:value2,数据字段名称n
:valuen}

网页表单数据选择列表的数据定义

待续…

主从结构,动态增加数据行

技术分享
如图所示,在HTML文档中,表单中一对多的从表(多行输入数据的table)定义如下:

<button id="testtable" type="button" onclick="insertRow()">测试插入一行</button><br>

<table id="dynamictable" fieldid="subdatas" subtable="3" border="1" cellspacing="0" width="400">
  <tr>
    <td>数据名称</td><td>数据类型</td><td>数值</td>
  </tr>
  <tr>
    <td><input type="text" subid="fieldid" subcol=0 name="fieldid" size=50></td>
    <td><input type="text" subid="fieldtype" subcol=1 name="fieldtype" size=20></td>
    <td><input type="text" subid="fieldvalue" subcol=2 name="fieldvalue" size=20></td>
  </tr>
</table>

使用JavaScript技术实现的动态添加一行的代码如下:

//定义插入一行表格的函数
function insertRow(){
  var dytb_id = ‘dynamictable‘;
  var dy_row_num = document.getElementById(dytb_id).rows.length;
  //取table中第二行单元格集合
  var dy_row = document.getElementById(dytb_id).rows[1].cells;
  //在table末尾,追加一行
  var dytb=document.getElementById(dytb_id).insertRow(dy_row_num);

  for (i = 0;i<dy_row.length; i++){
    var dy_td = dytb.insertCell(i);
    dy_td.innerHTML = dy_row[i].innerHTML;   
  } 
}

通过上面示例,在表单文档设计中,需要定义规则如下:

  • 动态增加行首先定义表头,再定义出一行输入控件;
  • 增加行的识别定义,用以确认是从表多行数据;
  • 每个单元格的定义,与表单数据字段定义方式一样。

网页表单解析

虽然通过网页文档做为审批表单,但也需要支持简捷的数据识别和简易的统计查询,这里采用MongoDB数据库做为底层数据库支撑。

解析目的及用处:

  • 解析文档中的数据字段及数值,并形成JSON数据;
  • 在文档中定义数据字段、业务规则,用以与流程衔接,需要解析定义;
  • 在文档中的定义,避开关系型数据复杂的管理,此模型可以追溯早期Lotus Notes/Domino数据库模型。

文档解析方式为通过遍历方式解析表单,表单数据形式涉及到单表及主从结构。而且,需要表单快速开发工具支撑。

网页表单定义解析

网页表单定义解析主要用于获取表单数据模型,用以为数据统计分析模型提供服务,形成数据接口模型。

网页表单业务数据解析

演示界面如下图所示。
技术分享

HTML文档定义如下:

<body>
<h1>表单元素遍历测试 JavaScript</h1>
<p id="demo" >这是表单数据解析示例.</p>
<div> 
<input id="name" fieldtype="char">名称</input><br>
通过自定义属性“fieldtype”来定义数据类型。<br><br>

<button id="testtable" type="button" onclick="insertRow()">测试插入一行</button>&nbsp&nbsp
<button id="test" type="button" onclick="getallelem()">测试解析表单数据</button><br><br>
<input fieldid="title" fieldtype="text" value="测试申请单" size=100>标题</input><br>
<input fieldid="old" fieldtype="number" value="42" size=100>年龄</input><br>
多行子表单,字段属性定义为“subid”,表单按数据字段属性定义,标识出含有子表,属性为“subtable”单独定义列数,其他不变。
<table id="dynamictable" fieldid="subdatas" subtable="3" border="1" cellspacing="0" width="400">
<tr>
<td>数据名称</td><td>数据类型</td><td>数值</td>
</tr>
<tr>
<td><input type="text" subid="fieldid" subcol=0 name="fieldid" size=50></td>
<td><input type="text" subid="fieldtype" subcol=1 name="fieldtype" size=20></td>
<td><input type="text" subid="fieldvalue" subcol=2 name="fieldvalue" size=20></td>
</tr>
</table>
<br><input fieldid="flag" fieldtype="text" value="end" size=100>结束标志</input><br>
</div> 
</body>

提取表单数据到JSON格式字符串的JavaScript函数如下所示:

function getallelem(){
    var elems = document.getElementsByTagName("*");
    var ret_json = "";  //定义返回JSON数据字符串
    var n = 0;          //JSON数据起点
    var m = 0;          //JSON嵌套子文档起点
    var subcolumns = 0;  //多行表单列数
    var subrows = 0;     //多行表单数据行数
    var row_num = 1;     //默认是一行数据

    for(var i=0;i<elems.length;i++){
        if (elems[i].hasAttribute("fieldid") && !(elems[i].hasAttribute("subtable"))){
            if (n == 0){
                ret_json += "\"" +elems[i].getAttribute("fieldid") + "\":\"" + elems[i].value + "\"";
            }else{
                ret_json += ",\"" + elems[i].getAttribute("fieldid") + "\":\"" + elems[i].value + "\"";
            }
            n++;
        }else{
            if (elems[i].hasAttribute("subtable")){
                subcolumns = elems[i].getAttribute("subtable");
                var tbl_id = elems[i].id;
                //取表单数据行数
                subrows = document.getElementById(tbl_id).rows.length - 1;
                ret_json += "\",\"" + elems[i].getAttribute("fieldid") + "\":[{\"";
                m = 0;
            }else{
                if (elems[i].hasAttribute("subid") && (m < subcolumns)){
                    if (m == 0){
                        ret_json += elems[i].getAttribute("subid") + "\":\"" + elems[i].value + "\"";
                    }else{
                        ret_json += ",\"" + elems[i].getAttribute("subid") + "\":\"" + elems[i].value + "\"";
                    }
                    m++;
                }else{
                    if (elems[i].hasAttribute("subid")){
                        ret_json += "},{\"" + elems[i].getAttribute("subid") + "\":\"" + elems[i].value + "\"";
                        m = 1;  
                        row_num++;  
                    }
                }
                if ((row_num == subrows) && (row_num>0) && (m == subcolumns)){
                    ret_json += "}]";
                    m=0,row_num=0;
                }
            }
        }
    } 
    alert("{" + ret_json + "}");    
}

网页表单文档存储

保存操作及事务处理

在保存网页表单文档操作中,需要把文档存储到MongoDB、和关系型数据库,二者不在一个事务中。因此,可以使用Cordys平台自动流程模型进行事务管理。

Created with Rapha?l 2.1.2函数函数HTMLHTML事务管理流程事务管理流程存储MongoDB环节存储MongoDB环节存储业务实例环节存储业务实例环节解析HTML文档()生成JSON数据()启动流程()调用存储表单数据Webservice()调用存储业务实例数据Webservice()

保存操作及非事务管理方式

Created with Rapha?l 2.1.2函数函数HTMLHTML非事务管理非事务管理存储MongoDB环节存储MongoDB环节存储业务实例环节存储业务实例环节解析HTML文档()生成JSON数据()保存文档操作()调用存储表单数据Webservice()调用存储业务实例数据Webservice()回写保存完毕Webservice()

由于作者水平有限,欢迎反馈交流。

参考:
JavaScript遍历HTML表单元素及表单定义 肖永威 2015.5
Cordys BOP 4平台开发实战——MongoDB提供文档服务(1) 肖永威 2015.4

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。