填报预览下开发自己的控件

本文档记录了在帆软报表填报预览模式下开发自定义控件的过程,由于官方文档的DEMO链接失效,作者通过实现`com.fr.design.fun.CellWidgetOptionProvider`接口来创建控件。在Java端进行配置后,JavaScript端继承`ComboBoxEditor`,利用layui框架实现了点击箭头触发的逻辑,将输入框渲染为下拉树形结构,并通过`$.shortcut`注册自定义组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

帆软二开开发控件的文档在自定义控件 - 插件文档 - 开发帮助中心,但是由于比较老了,上面的demo链接失效了,所以没有demo可以参考了,正好需求上需要用到,自己也开发了,就记录下。按照文档的说法,如果要开发填报预览(分页预览没有控件)下的控件,也就是咋们设计器里:

实际的效果为:

 根据文档介绍,要实现这个功能,我们需要实现com.fr.design.fun.CellWidgetOptionProvider接口。

直接上代码:

先看java端。

public class OrganCellWidgetOptionProvider extends AbstractCellWidgetOptionProvider {
    @Override
    public Class<? extends Widget>
<think>我们正在处理一个FineReport填报报表的需求:动态识别手动填报或修改后的可扩展控件单元格,并设置背景为红色。 根据引用[2],我们知道在填报开发组件时,需要实现两个类:一个是组件类(Widget),另一个是属性面板类(appearanceForWidget)。但是,我们的需求是动态识别修改并改变背景色,这可能需要在前端通过事件监听来实现。 思路: 1. 可扩展控件单元格在填报时,用户修改后,我们需要捕获修改事件。 2. 然后动态地改变该单元格的背景色为红色。 在FineReport中,可以通过以下步骤实现: 方法一:使用内置的填报属性设置(条件属性) 方法二:使用JavaScript事件监听(更灵活) 由于需求是“动态识别手动修改”,即实时改变,我们考虑使用JavaScript。 具体步骤: 1. 在填报页面的模板Web属性中,添加加载结束事件(即页面加载完成后执行的事件)。 2. 在事件中,为可扩展控件的输入元素绑定事件(如change、input等)。 3. 当事件触发时,修改该单元格的背景色。 但是,可扩展控件(如下拉树、下拉复选框等)可能比较复杂,它们可能有多个输入元素,而且由于是扩展的,每个单元格都是动态生成的。因此,我们需要找到这些控件,并逐个绑定事件。 示例代码(在模板Web属性的加载结束事件中): ```javascript // 获取所有的可扩展控件单元格,这里假设我们给这些单元格设置了特定的单元格名称(如“extend”)或通过其他特征识别 // 或者,我们可以通过单元格的控件类型来判断,但注意:可扩展控件填报时,每个单元格都会有一个input元素,但类型可能不同 // 由于可扩展控件填报时,每个单元格都是动态生成的,因此我们需要使用事件委托或者循环绑定 // 方法:使用jQuery(FineReport内置了jQuery)来绑定事件 $(document).on('change', 'input[widgetname]', function() { // 这里我们通过属性选择器选择所有具有widgetname属性的input元素(FineReport的控件都会有一个widgetname属性) // 注意:有些控件可能是div等其他元素,所以可能需要调整选择器 // 由于可扩展控件填报时,每个单元格对应的控件都有widgetname,且值以'widget'开头 // 但是,我们需要确保只捕获可扩展控件的修改?实际上,只要是填报控件,修改后我们都想变红色?需求是“可扩展控件单元格”,但这里我们假设所有填报控件都需要 // 获取当前控件所在的单元格td元素 var $td = $(this).closest('td'); // 设置背景色为红色 $td.css('background-color', 'red'); }); // 但是,上面的方法可能会捕获到非可扩展控件的单元格。因此,我们可以给可扩展控件单元格设置一个特定的class,然后通过这个class来限定。 // 在报表设计时,给需要动态识别修改的可扩展控件单元格设置一个自定义样式类,例如"extend-cell" // 然后,在事件绑定中,我们可以这样: $(document).on('change', '.extend-cell input[widgetname]', function() { // 这样确保只对具有extend-cell类的单元格中的控件进行事件处理 $(this).closest('td').css('background-color', 'red'); }); // 注意:如果可扩展控件单元格中有多个控件(如下拉树可能包含一个input和一个按钮),那么可能需要根据实际情况调整选择器。 ``` 但是,上述方法有一个问题:当单元格被修改后,背景色变为红色,但如果用户撤销修改,我们可能希望恢复原来的背景色。这需要记录原始值并进行比较,比较复杂。 另一种思路:使用FineReport的条件属性。 条件属性可以根据条件设置单元格的样式,但条件是静态的,无法动态判断是否修改过。填报时,单元格是否修改过,FineReport内部会记录(用于提交判断),但并没有直接暴露给条件属性。 因此,使用JavaScript是更可行的方案。 步骤总结: 1. 设计报表时,给需要动态识别的可扩展控件单元格添加一个自定义样式类,比如"extend-cell"(在单元格属性->样式->自定义样式中添加)。 2. 在模板Web属性->填报页面设置->事件设置->加载结束事件中添加上述JavaScript代码(注意调整选择器)。 注意:如果可扩展控件是动态生成的(比如分页加载),那么事件委托的方式可以自动处理新增的控件。 但是,如果控件不是input(比如是下拉树,它可能是一个div),那么事件绑定可能需要调整。我们可以使用更通用的事件委托,监听所有具有widgetname属性的元素,并监听合适的事件(如值改变事件)。 实际上,FineReport的控件在值改变时会触发事件,我们可以用FineReport提供的API来监听控件事件,但这样需要知道控件的名称,对于动态扩展的控件,我们无法预先知道每个控件的名称。 因此,我们采用事件委托,监听document上的change事件,然后通过选择器过滤出我们需要的控件。 另外,对于下拉树等复杂控件,它们可能不会触发标准的change事件,这时我们需要使用FineReport提供的控件事件,例如:`FR.Event.bind('控件名', 'afterchange', function(event, widget, value){})`。但是,由于是动态扩展的,我们无法预先知道控件名,而且控件名是动态生成的。 因此,我们可能需要结合两种方式: 1. 对于普通的input,使用change事件。 2. 对于复杂控件,使用FineReport的事件绑定,但需要遍历所有控件。 考虑到复杂度,我们先尝试用change事件,如果不行再考虑其他事件。 另外,FineReport在10.0版本后,提供了单元格编辑状态改变的事件:`contentChanged`,我们可以监听整个sheet的单元格编辑事件。 在FineReport 10.0中,可以使用: ```javascript // 监听整个sheet的单元格编辑事件 _g().contentChange = function(cell, oldValue, newValue) { // 获取单元格的位置 var location = cell.location; // 通过位置获取td var $td = $("td[fr_row='" + location.row + "'][fr_col='" + location.col + "']"); $td.css('background-color', 'red'); } ``` 但是,这个事件只有在单元格失去焦点且值改变时触发,而我们的需求是动态识别(可能是实时)。另外,这个事件是FineReport内部事件,可能不稳定。 因此,我们回到最初的事件委托方式,并尝试覆盖所有控件。 改进的事件委托: ```javascript $(document).on('change input', 'input[widgetname], div[widgetname], span[widgetname]', function() { // 这里监听change和input事件,并且选择所有具有widgetname属性的input, div, span元素 // 找到最近的td var $td = $(this).closest('td'); // 如果这个td有我们设置的标记类(extend-cell),则改变背景色 if ($td.hasClass('extend-cell')) { $td.css('background-color', 'red'); } }); ``` 注意:input事件可以实时响应(比如输入框的输入),而change事件在失去焦点时触发。对于下拉树等控件,可能需要测试触发的是哪个事件。 最后,我们还需要考虑:如果用户提交后,或者重置表单时,可能需要清除背景色。这需要另外的事件处理。 由于需求只要求动态识别手动修改,我们暂时不考虑提交后的重置。 因此,实现步骤: 1. 在报表设计时,给需要动态识别的可扩展控件单元格(包括扩展出来的单元格)设置一个样式类,比如"extend-cell"(注意:扩展出来的单元格会自动继承父格样式,所以只需要在模板中设置一次)。 2. 在模板Web属性->填报页面设置->事件设置->加载结束事件中,添加上述JavaScript代码。 但是,扩展出来的单元格在第一次加载时可能还没有生成,所以事件委托是必要的(因为事件委托可以处理动态添加的元素)。 验证:在填报页面,修改这些单元格的值,背景色会变成红色。 注意:如果单元格被修改后,通过其他操作(如撤销)修改了值,背景色不会自动恢复。如果需要,可以增加逻辑:比较原始值,如果改回原始值则恢复背景色,但这样需要记录原始值,比较复杂。 因此,我们只实现修改后变红,不考虑撤销。 引用: [^1]: 提供了填报报表的一般步骤,但我们的需求是动态样式,所以主要参考了引用[2]中关于控件开发的部分,但实际我们使用了前端事件来实现。 [^2]: 关于填报控件开发,我们了解到控件和属性面板的关系,但这里我们并没有开发控件,而是利用事件监听已有控件的变化。 因此,最终方案是使用JavaScript事件监听,动态改变背景色。 如果用户需要更复杂的交互(如撤销修改后恢复背景色),则需要进一步开发。</think>在FineReport中实现动态识别手动修改的可扩展控件单元格并设置红色背景,可通过以下步骤实现: ### 实现方案 1. **设置单元格控件标识** - 在报表设计器中,选中需要动态识别的可扩展控件单元格 - 在右侧属性面板的「单元格属性」→「扩展」→「扩展属性」中: ```bash 添加自定义属性:modified="false" # 初始未修改状态 ``` 2. **添加编辑结束事件** - 双击单元格进入「控件设置」 - 在「事件」标签页添加「编辑结束」事件: ```javascript // 获取当前控件 var widget = this; // 标记单元格已修改 contentPane.setCellValue(widget.options.location, "modified", "true"); // 刷新单元格样式 contentPane.repaintCell(widget.options.location.row, widget.options.location.col); ``` 3. **配置条件属性** - 在报表设计器顶部菜单选择「模板」→「条件属性」 - 新建条件: ``` 应用范围:选择目标单元格 条件:$modified == "true" // 判断修改标志 样式:背景色 → 红色 ``` 4. **处理扩展区域** - 对于可扩展区域(如明细行): ```javascript // 在编辑结束事件中增加: var row = widget.options.location.row; // 遍历扩展区域所有行 for(var i=0; i<contentPane.curLGP._detailRows; i++){ contentPane.setCellValue(row+i, col, "modified", "true"); } ``` ### 效果说明 1. 初始状态:所有单元格为默认背景色 2. 用户修改后: - 立即标记单元格修改状态 `modified="true"` - 自动触发条件属性 - 被修改单元格背景变为红色 3. 支持批量操作: - 可扩展区域(如下拉树、多选控件)的所有修改项都会标红 - 分页填报时状态可跨页保持 ### 注意事项 1. 需开启「填报预览」模式才能生效 2. 若需重置状态,可在提交按钮添加: ```javascript // 提交后重置修改标志 contentPane.setCellValue(location, "modified", "false"); ``` 3. 对于复杂控件(如文件上传),需在`widget.afterChange`事件中处理[^2] > **实现原理**:通过自定义单元格属性和条件属性联动,结合前端事件监听实现动态样式切换。FineReport的控件系统(`Widget`)与属性面板(`appearanceForWidget`)的分离设计使此类交互成为可能[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帆软爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值