FaaS 连接器 - 通过高级查询条件获取表单实例数据(包括子表单组件数据)
注意:不建议以 HTTP 连接器的形式在前端数据源中直接使用此 OpenAPI,请参考此案例配置 FaaS 连接器后方可使用。否则会导致 systemToken 参数的泄露,威胁应用的数据安全。
1. 使用场景
本例开发语言:NodeJS
本例介绍一下如何使用钉钉开放平台 OpenAPI 实现通过高级查询条件获取表单实例数据(包括子表单组件数据)。
2. 实现功能
2.1. 申请钉钉开放平台应用凭证及接口权限
若已申请,可忽略此步骤。
宜搭自定义连接器鉴权凭证申请及接口权限申请 | 钉钉宜搭·帮助中心
2.2. 创建并配置 FaaS 连接器
2.2.1. 创建 FaaS 连接器

2.2.2. 配置连接器基本信息和开发语言

2.2.3. 配置连接器执行动作



注意解析 Body 并配置成功标志位。
{
"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. 开发 FaaS 连接器
2.3.1. 前往云 IDE 开发并在 dingOpenApiUtil.js 文件中添加代码

添加完毕后需保存。
Windows:Ctrl + S
Mac:Command + S

复制下列代码,整个替换上图标记的「 searchFormDataSecondGeneration 」。
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. 将 faasEntry.js 文件中的代码完全替换
注意根据实际情况修改固定参数。
appKey、appSecret 为 2.1 申请的应用凭证。
systemToken 可直接在宜搭 应用设置 - 部署运维 中找到。

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. 部署 FaaS 连接器
注意保存添加的代码。

当提示代码部署成功即完成 FaaS 连接器云 IDE 开发。

2.5. 返回连接器配置并点击保存

2.6. 在宜搭页面配置数据源和使用数据源
2.6.1. 获取数据并展示在表格中
可参考下述案例,本例是对下述案例搜索数据功能的升级。
2.6.2. 在数据源中选择刚刚创建的连接器


2.6.3. 前端直接调用数据源
searchCondition(高级查询条件)参数格式说明:

// 加载表单数据
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();
}
3. 实现效果


4. 在线试玩
本文档对您是否有帮助?