在用户界面中实现动态列表的功能

图片

每个现代应用程序的界面以一种或另一种形式包含对象列表。 与他们一起工作时,用户通常需要相同类型的操作,例如排序,过滤,导出等。 由于列表可以是“动态的”,因此这些操作的实现通常会变得很复杂。 在这种情况下,数据将根据需要不仅从服务器读取到客户端,而且从数据库服务器读取到应用程序服务器。

在开放和免费的lsFusion平台中默认情况下所有列表都是动态的,并通过几行代码将其添加到任何形式。 在本文中,我将向您介绍其实现的一些技术细节,以及使用任何形式的任何列表时会自动提供给用户的界面功能。

创作


lsFusion中表单上的列表由OBJECTS语句添加:
OBJECTS i = Item
表格将被添加到表单中,其中Item类的所有对象都将包含在行中。 您可以将多个对象添加到一个列表中。 举个例子
OBJECTS (i = Item, s = Stock)
在这种情况下,该表将显示ItemStock类的所有可能的对象对。

使用PROPERTIES语句将列添加到列表中:
PROPERTIES name(i), name(s), quantityOnHand(i, s)
可以在表中添加对象的简单详细信息,以及包含分组,分区,递归等的任何表达式。

默认情况下,该列表将显示数据库中的所有对象。 要限制它们,可以使用FILTERS语句
FILTERS quantityOnHand(i, s) > 0
在过滤条件中,可以使用依赖于表单上任何对象的任何表达式。

导览


当用户打开表单时,平台将根据表的大小自动确定可见记录的数量。 为了简化表示,我们假设有50条这样的记录,在每个时刻,平台将在客户端和服务器上存储150条记录。 在这种情况下,当前活动对象应位于此“窗口”的中间:从第50条到第99条记录。 如果当前对象位于列表的最开始或结尾,则条目可能会更少。

如果在打开表单时需要使特定记录处于活动状态,则会向数据库服务器发出两个请求,每个请求在所需记录的每一侧读取75条记录。 然后,从其结果中粘贴一个常规列表。 如果您需要从头开始或从头开始初始化列表,则会对100条记录进行一个请求,并且将第一个或最后一个接收到的记录设置为活动状态。 如果用户在列表中按CTRL + HOME或CTRL + END转到列表的开头或结尾,则会发生相同的情况。

用户在当前窗口中间(第50个之前或第99个之后)之外进行活动记录时,平台将读取其他记录,以使当前记录位于新窗口的“正中央”。

这种动态列表实现的特殊之处在于,当前对象不能在窗口中间。 因此,在滚动列表时,当前对象会自动移动到可见区域。
图片


读取列表中的数据始终发生在两个查询中。 第一个查询仅读取临时表中必要记录的键。 第二个查询将为已读取的键读取所有列的值。 这样做的原因是,列可以包含可以被编译为子查询或其他复杂SQL构造的任何表达式。 在这种情况下,平台本身会将这些键推入子查询,以便这些列的值的计算不会遍及整个数据库,而只会根据必要的键进行。 由于进行了两次查询而不是一次查询,因此这会产生少量开销,但可以防止意外地“进入”低效率的数据库服务器计划。

筛选


可以根据以下选项过滤表单列表中的条目:

  • 使用FILTERS语句在连续选择代码中进行指示:
    FILTERS <>
    该表达式可以取决于表单上任何其他当前选择的对象。 例如,如果表单上有一个带有仓库的表或树,则在货物清单的表达式中,您可以引用当前仓库以仅过滤余额中的货物。
  • 选择代码中的指示,用户可以根据需要使用FILTERGROUP指令进行应用:
    FILTERGROUP myFilters
    FILTER 'Filter 1' <expression> 'F5' DEFAULT
    FILTER 'Filter 2' <expression> 'F6'

    下拉列表将添加到表单(如果组中有一个过滤器,则为复选框),用户可以使用该列表选择需要应用的过滤器之一。
    图片
  • 用户在界面中进行的手动自定义过滤:
    图片
    如果列表中的列不可编辑,则在输入字符时,此列的过滤器将自动打开,可通过按一下ESC键将其重置。

平台本身会监视可能影响当前过滤器的任何条件下的变化(相关对象的变化,用户操作等)。 当检测到此类更改时,将自动更新列表,而不更改当前选择的对象。 为此,发出了两个请求,在当前方向的每个方向上以及在初始化表格期间,每个方向有75个条目。

排序


默认情况下,列表中的条目按对象内部标识符的升序排列。 这些标识符是在创建对象时自动以升序生成的(同时,它们在所有类中都是全局唯一的),并且索引始终建立在它们之上。

列表中的排序可以如下更改:

  • 通过在代码中指示通过ORDER语句执行排序的列:
    ORDER column1(o) DESC , column2(o)
  • 双击用户的列标题(按住CTRL将添加“嵌套”排序)。
    图片

根据当前排序,在读取记录键时,相应的列表达式将被添加到请求的ORDER BY块中。 同时,始终将对象的唯一标识符添加到排序中,以确保所有记录的键都是唯一的。

将以下形式的表达式添加到请求的WHERE子句中:column1> value1 OR(column1 = value1 AND column2> value2)OR(column1 = value1 AND column2 = value2 AND key> value)。 同样,在读取键时,具有所需数量的可读记录的LIMIT指令将添加到请求中。 当读取记录“向上”时,ORDER BY中的顺序和WHERE中的表达式将相应地“翻转”,以沿相反方向读取记录。

应该注意的是,如果有适当的索引,执行这些查询的复杂度将相对较小(因为该索引将是仅针对给定数量的记录从当前键开始或向下的里程数)。 因此,当按列column1,column2进行排序时,为了加快处理动态列表的速度,建议构建以下索引:
INDEX column1(Object o), column2(o), o;
如果排序基于计算所得的列,则可以如本文所述将其永久存储,然后可以在其上建立索引。

这种实现的特征之一是缺少“诚实的”滚动条。 读取记录时,仅读取必要数量的记录。 通过使用所需的过滤器通过COUNT(*)获取列表中的总行数的请求可能导致表或索引的全部运行,这将对性能产生负面影响。 通过OFFSET构造读取记录时,将发生相同的问题。 另外,应该记住,在导航列表时,其他用户可以通过进行新的更改来更改列表中的条目数。

编辑中


令人惊讶的是,在某些甚至商业平台中,他们也无法实现在动态列表中进行编辑的功能。 实现此机制的主要困难在于,只有可见窗口存储在服务器和客户端上,并且可以在整个列表中进行更改。

lsFusion中没有特定的机制可以直接实现列表编辑。 此功能作为常规会话机制的一部分实现。

当前更改会话中进行的所有更改都存储在临时表中。 当用户编辑表单上的某些内容(包括其中一项的值)时,新值将使用适当的键写入临时表。 然后,当第二个查询(接收到键之后)读取列的值时,带有相应更改的临时表的JOIN会简单地添加到查询中。

保存更改会话时,将执行查询,该查询在一个事务中将所有值从临时表写入数据库。

小组调整


通常,用户需要一次更改列表中所有选定对象的列值。 为此,每个列表的工具栏中都有一个特殊按钮(使用F12热键)。 按下该键时,将激活正常的单元格编辑模式,但是更改不会应用于当前记录,而是应用于所有选定的记录。

此机制使您可以根据指定的条件快速编辑大量对象:
图片


与正常编辑期间一样,更改不会立即保存到数据库中,而是记录在临时表中。 然后,用户将需要单击“ 保存”按钮以将它们写入数据库。 这种方法的缺点可能是用户意外更改了额外的数据。 但是正如他们所说,这一原则在这里起作用:“权力越大,责任就越大”。

清单摘要


在任何列表中,都使用户有机会按当前选择中的特定列查找记录数或数量。 为此,用户需要单击特定列表工具栏中的相应按钮:
图片


要获取此数据,将使用表达式COUNT(*)或SUM自动生成一个请求,并在其中添加当前选择表达式。 使用此功能,您可以快速从列表中获取总计,而不必依靠生成报告。

在客户端的桌面版本中,还可以通过类似于Excel的方式来计算所选单元格的总和:
图片


复制/粘贴


在桌面版本中,用户可以标记某些单元格,按CTRL + C,然后将其中的值粘贴到剪贴板中:
图片


同样,您可以将表格从剪贴板粘贴到任何形式的任何可编辑列表中:
图片

这种机会通常是发展专门进口产品的替代方法。

表设置


在任何列表中,您都可以更改其一些参数:
图片

您可以更改列的组成,其大小,标题,蒙版等。 您可以为当前用户和所有用户保存表设置(如果当前用户具有必要的权限)。

请注意页面大小选项。 使用它,您可以调整本文开头所述的“窗口”的大小。 例如,您可以指定一个较大的值,而不是自动输入50条。 然后,大量数据将被下载到客户端和服务器,但是请求的发生频率将降低。 将此参数的值设置为0可使它在任何动态列表中正常显示,也就是说,将始终读取列表中的所有条目。 也可以使用DESIGN语句的pageSize参数在代码中直接指定窗口的大小。

导出到Excel


对于任何列表,都可以在Excel中上载其所有记录。 为此,只需单击以下按钮:
图片

这将考虑当前的选择,排序以及仅在表设置中指定的可见列。

旋转


默认情况下,任何列表都显示为表格。 但是可以将其切换到特殊的显示模式,在该模式下,用户可以构建各种报告和图表:
图片


列表中的条目数量很少,数据将直接在客户端上处理。 一旦数据量超过特定阈值,服务器上自动生成的数据库查询将用于对数据进行分组。

另类


出现一个合理的问题。 如何解决在不支持此功能的平台中编辑动态列表的问题。 通常,它们制作一个简单的列表,迫使用户通过某些选择来限制条目的数量(例如,按类别,供应商或其他相关目录指定过滤器)。

但是,这种方法存在一个严重的问题。 即使已建立选择,也不能保证样本中不会有大量记录。 不可能预先计算获得的值的数量,因为这样的操作的复杂度通常可以直接与获得所有数据的复杂度相比。 因此,在某些情况下,大量条目将添加到列表中,这将导致服务器或客户端上的资源大量消耗,以及性能的显着下降。

结论


在现代开发中实现动态列表并不是最琐碎的任务,因为客户端和服务器部分都涉及到。 世界上有许多具有开放许可证的开放源代码库,可让您快速方便地实现此功能。

在开放和免费的lsFusion平台中,动态列表是用几行代码创建的,并为用户提供了大量使用它们的机会。 结合编辑此类列表的功能,该平台使您可以快速处理成千上万行的文档,组织选择文档中记录的便捷工作,对目录进行组更改等。

通过使用有限的数据集,动态列表的使用可以显着减少服务器和客户端上处理器时间和内存的消耗,并减少服务器和客户端之间的通信通道上的负载。 由于效率如此之高,八个最大的零售链中的五个在白俄罗斯基于lsFusion平台的解决方案上开展了主要的运营活动。

Source: https://habr.com/ru/post/zh-CN484648/


All Articles