FaaS connector-obtain form instance data (including subform Component Data) through advanced query conditions
Note: We do not recommend that you use this OpenAPI directly in the front-end data source as an HTTP connector. For more information, see configure FaaS connectors in this case. Otherwise, systemToken parameters will be leaked, threatening the data security of the application.
1. Usage scenarios
The development language of this example is NodeJS
This example describes how to use the DingTalk open platform OpenAPI to obtain form instance data (including subform Component Data) through advanced query conditions.
2. Implement functions
2.1. Apply for DingTalk open platform application credentials and interface permissions
If you have applied, you can ignore this step.
宜搭自定义连接器鉴权凭证申请及接口权限申请 | 钉钉宜搭·帮助中心
2.2. Create and configure FaaS connectors
The interface used in this example is:通过高级查询条件获取表单实例数据(包括子表单组件数据) - 开放平台
Note:
- Switch to the new search storage structure and increase the maximum number of list queries from 5000 to 30000.
For more information, see:2022.04.21 版本更新-OpenAPI 全新升级 | 钉钉宜搭·帮助中心
2.2.1. Create FaaS connector
2.2.2. Configure connector basic information and development language
2.2.3. Configure connector execution actions
Note that the Body is parsed and the success flag bit is configured.
{
"appType" : "String",
"formUuid" : "String",
"pageNumber" : "Integer",
"pageSize" : "Integer",
"originatorId" : "String",
"searchCondition" : "String",
"orderConfigJson" : "String",
"modifiedToTimeGMT" : "String",
"modifiedFromTimeGMT" : "String",
"createToTimeGMT" : "String",
"createFromTimeGMT" : "String"
}
{
"success": true,
"content": "",
"error": ""
}
2.3. Develop FaaS connectors
2.3.1. Go to Cloud IDE development anddingOpenApiUtil.jsAdd code to the file
You need to save it after adding it.
Windows:Ctrl + S Mac:Command + S
Copy the following code to replace the searchFormDataSecondGeneration marked in the preceding figure 」.
searchFormDataSecondGeneration: async function (searchFormDataSecondGenerationInputs) {
let client = createClient();
let searchFormDataSecondGenerationHeaders = new $dingtalkyida_1_0.SearchFormDataSecondGenerationHeaders({});
searchFormDataSecondGenerationHeaders.xAcsDingtalkAccessToken = innerGetAccessToken();
let searchFormDataSecondGenerationRequest = new $dingtalkyida_1_0.SearchFormDataSecondGenerationRequest(searchFormDataSecondGenerationInputs);
try {
const result = await client.searchFormDataSecondGenerationWithOptions(searchFormDataSecondGenerationRequest, searchFormDataSecondGenerationHeaders, new $Util.RuntimeOptions({}));
return result.body;
} catch (err) {
if (!Util.empty(err.code) && !Util.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
}
throw err;
}
return null;
},
2.3.2. Replace the code in the faasEntry.js file completely.
Modify the fixed parameters according to the actual situation.
The application credentials applied for with appKey and appSecret as 2.1.
systemToken can be found directly in YIDA application settings-deployment O & M.
const { openApi: OpenAPIUtil, yidaConnector: YidaConnectorUtil, httpUtil: HttpUtil } = require('./utils');
const { ConnectorTypeEnum } = YidaConnectorUtil;
// 注意:涉及数据安全的参数(如:appKey、appSecret、systemToken)一定要在服务端发送,不可在前端数据源里传入。
const appKey = 'XXXXXXXXXXXXXXXXXXXX';
const appSecret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const systemToken = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
module.exports = async function (faasInputs, context) {
// 这里的 inputs 跟你配置连接器时的 Body 参数及字段格式保持一致
const { inputs = {}, yidaContext = {} } = faasInputs || {};
const userId = yidaContext ? yidaContext['userId'] : ''; // 从连接器上下文获取调用人的 userId
const corpId = yidaContext ? yidaContext['corpId'] : ''; // 从连接器上下文获取调用组织的 corpId
const accessToken = yidaContext ? yidaContext['accessToken'] : '';
const consumeCode = yidaContext ? yidaContext['consumeCode'] : '';
OpenAPIUtil.setAccessToken(accessToken);
await OpenAPIUtil.getCustomAccessTokenThenCache(appKey, appSecret); // 获取调用连接器的 accessToken
YidaConnectorUtil.setConsumeCode(consumeCode);
inputs['systemToken'] = systemToken;
inputs['userId'] = userId;
return await searchFormDataSecondGeneration(inputs).then((result) => {
return {
success: true,
content: result,
error: null,
};
}).catch((error) => {
return {
success: false,
content: null,
error: error,
};
});
};
async function searchFormDataSecondGeneration(inputs) {
return await OpenAPIUtil.searchFormDataSecondGeneration(inputs);
}
2.4. Deploy FaaS connector
Save the added code.
When the code is successfully deployed, the FaaS Connector Cloud IDE development is completed.
2.5. Return to the connector configuration and click save
2.6. On the YIDA page, configure data sources and use data sources
2.6.1. Obtain data and display it in a table
For more information, see the following example. This example is an upgrade to the data search function of the following cases.
2.6.2. Select the connector you just created in the data source
2.6.3. The frontend directly calls the data source.
searchCondition (advanced query criteria) parameter format description:
// 加载表单数据
export function getData() {
const { currentPage, pageSize, searchCondition = [], } = this.state;
this.dataSourceMap.getData.load({
inputs: JSON.stringify({
body: {
appType: pageConfig.appType,
formUuid,
pageSize,
pageNumber: currentPage,
searchCondition: JSON.stringify(searchCondition),
},
}),
}).then(res => {
const { content, success, error } = res;
if (!success) {
this.utils.toast({
title: error,
type: 'error',
});
this.setState({
loading: false,
});
return;
}
const result = (content.data || []).map((item) => {
const { formInstanceId, formUuid, formData } = item;
return {
formInstId: formInstanceId,
formUuid,
...formData,
};
});
this.setState({
tableData: {
currentPage: content.pageNumber,
data: result,
totalCount: content.totalCount,
},
loading: false
});
}).catch(error => {
this.utils.toast({
title: error.message,
type: 'error',
});
this.setState({
loading: false,
});
});
}
// 搜索
export function onSubmit(values) {
const searchCondition = [{
'key': 'textField_lcpug407', // 姓名
'value': values.textField_lpas7xw1,
'type': 'TEXT',
'operator': values.selectField_lpb05kua,
'componentName': 'TextField',
}, {
'key': 'selectField_lpgn09sv', // 性别
'value': values.multiSelectField_lpgpe5te && values.selectField_lpgpe5td === 'eq' ? values.multiSelectField_lpgpe5te[0] : values.multiSelectField_lpgpe5te,
'type': 'ARRAY',
'operator': values.selectField_lpgpe5td,
'componentName': 'RadioField',
}, {
'key': 'numberField_lcpusnib', // 年龄
'value': values.numberField_lpgpe5tf,
'type': 'DOUBLE',
'operator': values.selectField_lpgpe5tg,
'componentName': 'NumberField',
}, {
'key': 'multiSelectField_lpgn09su', // 擅长技术
'value': values.multiSelectField_lpgpe5th,
'type': 'ARRAY',
'operator': values.selectField_lpgpe5ti,
'componentName': 'MultiSelectField',
}, {
'key': 'dateField_lpbyrnq7', // 入职日期
'value': values.dateField_lpgpe5tj,
'type': 'DOUBLE',
'operator': values.selectField_lpgpe5tk,
'componentName': 'DateField',
}, {
'key': 'employeeField_lpgn09st', // 直属主管
'value': values.employeeField_lpgpe5tl ? (values.selectField_lpgpe5tm === 'eq' ? values.employeeField_lpgpe5tl.value : values.employeeField_lpgpe5tl.map(item => item.value)) : '',
'type': 'STRING',
'operator': values.selectField_lpgpe5tm,
'componentName': 'EmployeeField',
}];
this.setState({
currentPage: 1,
loading: true,
searchCondition,
});
this.getData();
}