对于一个页面来说,它需要从服务端获取数据用于展示,也需要进行一些增删改的操作。 在平台中,模型层的概念使得能够语义化的提供对模型资源操作的API,也就是各种业务动作。这些业务动作与前端的UI控件应当是解耦的。 另外,对于单个场景的页面来说,例如表单、清单、图表等,它的数据源是单一的,无需复用的。而对于一个复杂页面来说,它的数据往往存在复用性。例如明细表中的表格数据同时使用图表来展现。 因此,为了解耦与复用,我们定义了数据源。
数据源具备以下基本特性:
关联一个可提供数据服务的元素
提供增删改查、自定义等对资源的操作
目前,UX支持使用对象、领域模型、DeepQL、财务模型、Dataframe(Python)作为数据源。
在使用视图中,每一个数据源都会以 $dataSources.数据源编码 的形式被控件和表达式访问。一个典型的数据源具备以下能力:
数据结果:保存最近一次查询返回的数据列表,可结合分页信息只展示当前页。
字段信息:包含每个字段的编码、名称、类型等,便于清单表、图表等根据字段做展示和筛选。
查询模式:支持“批量(list)”“单条(single)”两种模式,对应清单场景和明细场景。
分页与排序:可以配置每页条数、当前页以及多字段排序方式。
过滤条件:既可以在数据源配置中预置过滤规则,也可以结合筛选器/表达式在使用时动态设置过滤条件。
状态反馈:在查询、增删改操作过程中,会维护 loading 状态和错误信息,用于在页面上给出反馈。
通过这些能力,UX 中的表单、清单表、图表等控件可以在不感知底层接口细节的情况下,专注于展示和交互逻辑。
创建好UX元素,进入UX页面后,切换到数据源管理的菜单,点击添加按钮创建数据源,选择数据源的类型

对象/业务模型数据源主要用于基于模型3.0的数据的增删改查。基于其创建数据源后,可以进一步创建清单表、明细表等控件。
业务模型创建: 通过业务模型创建后会带出模型下所有对象及对象的属性与链接,可以通过勾选开选择启用哪些属性、链接、对象。

对象创建: 创建出的数据源只会包含该对象的属性与链接。
创建对象/模型数据源时,默认的查询模式为批量。也可以切换为单条,两者的典型应用场景如下:
批量:清单表、卡片列表等列表展示/管理场景,需要分页、排序、筛选,或为图表提供一整批明细数据。
单条:明细表、详情页等针对某条业务数据进行查看和编辑的页面,通常由列表/图表点击或跳转参数定位一条记录。
批量模式下,每次会返回多条数据,适合“浏览 + 批量操作”;单条模式下,每次只返回一条记录,适合“选中一条后展示详情”,避免一次性查询大量数据。

过滤方式的配置可以实现对数据源获取的多条数据做筛选。配置为过滤条件的属性或链接可以作为一个条件与一个FX表达式/一个UX变量/一个控件值/一个固定值/做比较。

开启【参数变化时自动执行】后,当数据源查询条件中依赖的控件值、变量或表达式结果发生变化时,系统会自动重新查询该数据源,并刷新绑定到该数据源的控件。
推荐开启的场景:
列表页或图表页中,用户通过筛选器(POV)、下拉框等控件调整查询条件,希望实时刷新清单表或图表;
单条模式下,业务主键来自“列表行点击”“跳转参数”等,变更后应立即刷新详情;
过滤条件较轻、接口耗时可接受的查询。
不建议开启的场景:
明细编辑表单中,用户在未保存前频繁修改某些字段,但这些字段又被用作查询条件,可能导致数据源被反复刷新、覆盖当前编辑内容;
后端查询代价较大,希望由用户手动点击“查询”“刷新”等按钮时才发起请求。
在不勾选【参数变化时自动执行】的情况下,可以通过“查询数据源”动作,在合适的时间点(例如点击按钮、提交筛选条件后)手动触发查询。
支持配置默认排序与按指定列排序。选择指定列排序后可以选择多条属性与链接,并按升序或降序的顺序进行排序。

财务模型数据源可以关联财务模型,并配置相应的维度表达式,用于从财务模型取数。
取数模式包括UI模式与脚本模式两种,支持多行多列的取数形式。
由于其目前主要用于图表的展示,可参考图表相关的说明文档:
对于DeepModel而言,往往需要进行复杂的关联查询与数据展示,目前可以通过编写Deepql实现,其原理类似于编写sql。并可以通过变量实现页面筛选条件与数据的联动关系。
配置步骤如下:
1、在模型主视图中,选择查询器,并编写deepql查询语句。具体语法详见模型相关配置文档。

2、在UX中添加DeepQL数据源,则将自动获取语句返回数据的结构与变量信息。在变量中填入页面的表达式,则可实现相应的联动效果

为了能够实现更复杂的数据处理并支持定制化开发,UX也支持了python数据源来进行任意的接口请求。
可以通过特定形式编写一个python脚本,实现将一个dataframe返回至前端页面用于图表展示或其他后端数据获取。
相应语法细节可参考Python sdk文档:
1、编写python脚本,返回维度相关数据
from deepfos.lib.deepux import Struct, String, to_desc, Json, as_datasource
from deepfos.element import Dimension
import pandas as pd
import json
class Data(Struct):
entity = Json('entity')
@as_datasource(struct=Data)
def main(p2):
dim = Dimension('Entity')
res = dim.query('Descendant(#root,0)', fields=['name', 'ud1'], as_model=False)
dims = []
for dim in res:
if dim['ud1'] == 'otbase':
dims.append(dim['name'])
return pd.DataFrame(
{
"entity":dims
}
)
2、在UX中添加python数据源

3、通过表达式获取到数据源的值,以实现例如动态显隐等效果

($dataSources.data_py_get_entity_ud_KKZS.data || []).map(i => i.entity)?.includes($components.entity.value) ? true : false
1、编写python脚本,获取财务模型数据并进行计算
import numpy as np
from deepfos.lib.deepux import Struct, UUID, Json, Float, Integer, DateTime, Boolean, String, as_datasource
import pandas as pd
from deepfos.element.finmodel import FinancialCube
from deepfos.lib.deepux import to_desc, as_datasource
from deepfos.element.dimension import Dimension
class Data(Struct):
Version: String
Period: String
Entity_p: String
Category1: String
Material: String
Account: String
Category2: String
Currency: String
Scenario: String
SaleNo: String
Entity_s: String
Supplier: String
Customer: String
Brand: String
Misc: String
Year: Float
Year_last: Float
colour: String
@as_datasource(struct=Data)
def main(p1, p2):
if None in [p2['Year'], p2['Period'], p2['Category1'], p2['Entity_p']]:
return pd.DataFrame()
Year = p2['Year']
Year_last = str(int(p2['Year']) - 1)
Period = p2['Period']
Category1 = list_to_str(p2['Category1'])
Entity_p = p2['Entity_p']
cube = FinancialCube('bgbz_planning_cube')
fix = f'Version{{WorkVersion}}->Year{{{Year};{Year_last}}}->' \
f'Period{{{Period}}}->Entity_p{{{Entity_p}}}' \
f'->Category1{{{Category1}}}->' \
f'Material{{Mat1}}->' \
f'Supplier{{NoSupplier}}->' \
f'Account{{BOM11}}' \
f'->Category2{{NoCategory}}->Currency{{CNY}}->Scenario{{Actual}}->Misc{{NoMisc}}->' \
f'SaleNo{{NoSaleNo}}->Customer{{NoCustomer}}->Brand{{NoBrand}}->Entity_s{{NoEntity}}'
df = cube.query(fix, compact=False, pivot_dim='Year')
if df.empty:
raise ValueError("数据为空")
if Year not in df.columns:
raise ValueError(f"当年({Year}年)数据为空")
if Year_last not in df.columns:
df['Year_last'] = np.nan
df.rename(columns={Year: 'Year', Year_last: 'Year_last'}, inplace=True)
df = df[df['Year'].notnull()]
df['colour'] = df.apply(lambda x: get_color(x), axis=1)
desc_Category1 = Dimension(element_name='Category1')
Category1_dim_desc = {'Category1': to_desc(desc_Category1.query(expression='Base(#root, 0)'))}
return df, Category1_dim_desc
def get_color(x):
if np.isnan(x['Year_last']):
return '本年当期 '
else:
if x['Year'] >= x['Year_last']:
return '本年当期'
else:
return '本年当期 '
def list_to_str(string_list):
string = ''
for i in string_list:
string += i
string += ';'
string.rsplit(';')
return string
if __name__ == '__main__':
try:
from _debug_alpha import para1, para2
except ImportError:
para1 = para2 = {}
para2 = {'Year': '2023', 'Period': '1', 'Entity_p': 'An10301',
'Category1': ['A330_N', 'A500_N', 'A321117_N', 'A341111_N', 'A311213_N', 'A321114_N', 'A321118_N',
'A355_N', 'A550_N', 'A321116_N', 'stubby250_N', 'ASLEEK250_N', 'AZ21114_N', 'B221215_N',
'B211112_N', 'B221115_N', 'AZ11212_N', 'A311217_N', 'A473_SLIM_N', 'A321115_N', 'B211212_N',
'AZ11211_N', 'AZ11114_N', 'ASIp250_N', 'ASIp310_N', 'ASIp270_N', 'ASIp200_N', 'ASLEEK270_N']}
main(para1, para2)
2、在UX中添加python数据源

3、图表可以选择该python数据源,并进行图表的可视化配置

回到顶部
咨询热线
