xinglie / report-designer

⚡打印设计、可视化、标签打印、编辑器、设计器、数据分析、报表设计、组件化、表单设计、h5页面、调查问卷、pdf生成、流程图、试卷、SVG、图形元素、物联网、标签纸
https://xinglie.github.io/report-designer/
902 stars 232 forks source link

表单-数据采集 #40

Closed xinglie closed 7 months ago

xinglie commented 3 years ago

该元素基于"数据-数据表格"构建而来,数据表格帮助信息可参考:数据-数据表格

首先添加“数据采集”元素到设计区

image

因为要在一个表格中完成复杂的操作,所以在左侧会提示相应的行完成什么样的需求

行介绍

它可与下面的标题行配合制作复杂的表头,也可以作为容器,承载其它元素。头支持添加行、拆分、合并单元格等操作。

如果不需要,可以在属性面板中对头进行隐藏

标题行

用于描述数据列的标题,标题行只允许一行,且不允许合并拆分单元格,如果需要复杂的表头,需要和头进行配合使用。

数据行

用于显示静态数据或输入框,用于采集数据,数据行支持添加、删除行,但在只有一行时,禁止删除。同时它也不支持拆分合并单元格

合计行

用于对数据行的求和等功能,它也不支持添加行、拆分单元格等操作

如不需要,可以在属性面板中隐藏

与头的功能相同,支持添加行、拆分、合并单元格等操作,允许自定义复杂的格子。 如不需要,可在属性面板中隐藏

数据采集头、合计、尾隐藏后,就是一个基础的表格

设置输入框

除合计行外,其它单元格均支持设置单元格内容为输入框

image

首先选中某个单元格,在右侧属性面板中,格子内容选择输入框即可

不同的格子内容,下方可供配置的选项不同,输入框的相关配置信息可参考:表单-输入框

至此我们就完成了在设计器中对“数据采集”的介绍,关于使用请参考下方的使用说明

xinglie commented 3 years ago

使用说明

设计完成后的“数据采集”元素,可以拿出来在其它页面中单独使用。

如何独立使用参考:独立使用设计元素

事件派发

数据采集向外派发elementinput事件,在输入框有任何输入变化时,均会向外派发该事件。可以在该事件内获取用户所有的输入以及对内容做校验等

派发的事件参数对象如下

elementType: 'form-collect',//针对数据采集元素则是写死的form-collect
elementProps: stringifyProps,//数据采集元素包含子元素序列化后的JSON字符串,包含用户输入,可供还原界面使用
elementValue: values,//针对所有输入框单独提取的一份独立的用户输入数据
elementInputs//所有可供用户输入的输入框DOM对象

监听、收集数据

假设html结构如下

<body>
    <div class="page-root">
      <div id="form_collect"></div>
    </div>
</body>
<script src="path/to/standalone.js"></script>
<script>
designer.element('#form_collect',{...});
</script>

可以在form_collect自身或任意祖节点上监听,因为elementinput是一个冒泡事件。 如在document.body上监听事件

<body>
    <div class="page-root">
      <div id="form_collect"></div>
    </div>
</body>
<script src="path/to/standalone.js"></script>
<script>
document.body.addEventListener('elementinput',console.log(e));
designer.element('#form_collect',{...});
</script>

当用户有任何输入时,均会在控制台中打印出相应的数据。

验证数据

假设需要对全部或部分输入框做校验,也是在elementinput事件中处理,如

<style>
html body .red{border-color:red!important}
</style>
<body>
    <div class="page-root">
      <div id="form_collect"></div>
    </div>
</body>
<script src="path/to/standalone.js"></script>
<script>
document.addEventListener('elementinput',e=>{
    for(let input of e.elementInputs){
        if(input.value && !/^\d+$/.test(input.value)){//如果输入不是数字
            input.node.classList.add('red');//使输入框变成红色框
        }else{
            input.node.classList.remove('red');//如果合法,移除红色框
        }
    }
    console.log(e);
});
designer.element('#form_collect',{...});
</script>

数据采集元素初始化完成后,会自动派发一次elementinput事件,这主要是为了完成如上的数据验证,同时也是为了处理下面提到的回显

回显

回显有2种方式

回显方案一

如果在elementinput事件中,把事件对象的event.elementProps这个字符串保存了下来,则回显时,把元素的props直接设置为该字符串即可完成回显

回显方案二

如果在elementinput事件中,把事件对象的event.elementValue保存了下来,则按如下方式进行回显设置

<body>
    <div class="page-root">
      <div id="form_collect"></div>
    </div>
</body>
<script src="path/to/standalone.js"></script>
<script>
designer.element('#form_collect',{
    id:"e_180",
    type:"form-collect",
    data:formCollectData
    props:{
       //...
    }
});
</script>

在渲染“数据采集”元素时,需要在JSON数据中,如上增加一个data属性,formCollectData即是前面elementinput事件中提到的event.elementValue对象。

如果采用该方案,则props对象中使用设计器产出的即可,不要求是elementinput事件中产出的event.elementProps这个字符串。

“数据采集”元素会根据数据data和配置信息props进行数据合并,产生最终事件elementinput中需要的elementProps字符串,这也是为什么初始化后也会派发一次elementinput的原因之一。

直接获取数据

如果不方便使用事件监听的方式进行获取数据,则可以使用该方法

首先调用designer.getVframe方法拿到内部的vframe对象,再通过它调用invoke('getValue')即可拿到前述的事件对象中的数据。

完整示例如下

<body>
    <div class="page-root">
      <div id="form_collect"></div>
    </div>
</body>
<script src="path/to/standalone.js"></script>
<script type="module">
designer.element('#form_collect',{...});
let vf = await designer.getVframe('#form_collect');
let result = await vf.invoke('getValue');
// 或者使用promise版本

designer.getVframe('#collect').then( vf => vf.invoke('getValue')).then( result => console.log(result));

</script>

线上demo页面:https://xinglie.github.io/report-designer/standalone.html 源码页面:https://github.com/xinglie/report-designer/blob/master/standalone.html

xinglie commented 3 years ago

动态添加行

仅数据行支持在最终用户使用时,可动态添加和删除行。

仅能删除动态添加的行,不能删除设计器中设置的原始行。

动态添加的行添加在最后一行数据行那里,即合计行的前面。

只读模式

<body>
    <div class="page-root">
      <div id="form_collect"></div>
    </div>
</body>
<script src="path/to/standalone.js"></script>
<script>
designer.element('#form_collect',{
    id:"e_180",
    type:"form-collect",
    readonly:trueOrFalse,//如果readonly为true,则数据采集表格只读,无添加删除行的按钮,所有input框增加readonly属性
    props:{
       //...
    }
});
</script>