OA待办连接器系统模板

按泛微、蓝凌、致远、云之家分类的 OA 待办消息模板库:审批待办、业务待办、消息提醒的新增/处理/删除模板与配套函数实现,复制即可使用。

现在统一推荐函数模式:按泛微、蓝凌、致远、云之家分类的 OA 待办消息模板库,覆盖审批待办、业务待办(BPM / 阶段任务)、消息提醒的新增 / 处理 / 删除模板与配套函数实现,复制即可使用。
本文不是产品概述,而是把线上正在运行的 OA 待办连接器拆成可直接复制的配置块:每个 OA 系统固定四段——连接配置、场景参数、配套函数、验收清单。所有域名、注册码、appId、secret、企业 EI、客户名称都已替换为占位符。

使用前必读(免责声明)

本文档根据线上已正式启用的 OA 待办连接器配置和当前生效的 APL 函数整理总结,暂未逐项经过真实 OA 系统联调校验。不同 OA 版本、租户定制和接口升级都可能造成端点、字段名或状态位差异;如发现文档与现场不一致,请联系集成平台值班同学反馈修改。

怎么用(5 分钟)

  1. 先按 OA 系统找到对应章节,照 1.1 / 2.1 / 3.1 / 4.1 配连接。
  2. 按待办类型复制新增、处理、删除三个场景模板,URL 填该系统的端点。
  3. 把本章的 oaRequest / dataDetail 函数建好,再到连接页「函数参数配置」点「重新设置」挂上;无入参时保持“未设置”。
  4. 用一条测试待办走完新增 → 处理 → 删除,再批量上线。

线上配置总表(先看结论)

OA 系统 / 路线常用端点结果解析(典型值)函数新增 → 处理 → 删除删除关键写法
泛微 / 标准接口/rest/ofs/ReceiveRequestInfoByJsonoperResult · message · 1oaRequest + dataDetailisremark 0 → 2;viewtype 0 → 1deleteUserRequestInfoByJson 或 deleteRequestInfoByJson
泛微 / 预置接口/rest/ofs/fxiaokeReceiveRequestInfoByJsonoperResult · message · 1oaRequest + dataDetailisremark 0 → 2;type 1/2/3/4isremark 0 + ifdelete=1,viewtype 保持 0
泛微 / E10/papi/openapi/api/open_intunifytodo/server_engine/receiveRequestInfooperResult · message · 1oaRequest + dataDetailisremark 0 → 2isremark 4
蓝凌 / 新版 notifybus/openapi/sys-notifybus/v2/main/sendsuccess · msg · truedataDetailsend → done → removeTodoremoveTodo
蓝凌 / 旧版 sendTodo/api/sys-notify/sysNotifyTodoRestService/sendTodoreturnState · message · 2dataDetailsendTodo → setTodoDone → deleteTododeleteTodo
致远/seeyon/rest/thirdpartyPending/receive/pendingserrcode · errmsg · 200oaRequest + dataDetailstate 0 → 1flagTax + subState 2
云之家/gateway/newtodo/open/generatetodo.json?accessToken=errorCode · error · 200oaRequest + dataDetailgeneratetodo → action.jsonactiontype {"delete":1}
结果解析只是线上典型值,不同 OA 版本可能不同;复制后先用一条真实数据看返回体,再确定 codeName / msgName / successCode。

〇、通用规则

0.1 连接配置页(按页面顺序)

连接配置页从上到下就是三块:基础配置、通用参数配置(Header + 结果格式配置)、函数参数配置。按下面顺序逐块填,不要跳步。
页面区域页面字段对应小节
基础配置连接名称、*对接的系统名称0.1.1
通用参数配置Header、结果格式配置0.1.2、0.1.3
函数参数配置函数参数0.1.4

0.1.1 基础配置

页面字段填写内容
连接名称自定义,建议带 OA 系统名,如 泛微OA待办 / 蓝凌OA待办
*对接的系统名称必填,按实际 OA 填写,如 泛微 OA

0.1.2 通用参数配置:Header

页面就是两列 KEY / VALUE。线上多数连接显示“暂无数据”,说明 Header 不是必填;只有 OA 明确要求固定请求头时,才按下表加行。
KEYVALUE
Content-Typeapplication/json
acceptapplication/json
AuthorizationBasic <Basic认证串>
说明:Content-Type 多数接口需要,平台已自动带时可不加;accept 部分泛微接口可选;Authorization 仅蓝凌等接口要求,线上多数蓝凌连接使用。不要三行全抄,按 OA 文档只保留需要的。
  1. 在 Header 表中新增一行,KEY 填请求头名称,VALUE 填固定值。
  2. 只放固定值;动态 token、签名、时间戳不要写在这里,统一放 oaRequest 函数。
  3. secret、appSecret 不写进连接页面;页面配置对租户管理员可见。
  4. 保存前核对 KEY 与 OA 文档一致,不要多空格。

0.1.3 通用参数配置:结果格式配置

页面就是 KEY / VALUE 两列,固定五行:codeName、msgName、dataName、successCode、xmlJsonField。下面按 OA 系统给出可直接照填的五项值,先找到自己的系统,再把 VALUE 抄到对应行。
【泛微 / 标准接口、预置接口】
KEYVALUE
codeNameoperResult
msgNamemessage
dataName(留空)
successCode1
xmlJsonField(留空)
【泛微 / E10】
KEYVALUE
codeName$.message.errcode
msgName$.message.errmsg
dataNamedata
successCode200
xmlJsonField(留空)
【泛微 / ESB】
KEYVALUE
codeNameRTNCODE
msgNameRTNMSG
dataNameRTNDATA
successCodeS
xmlJsonField(留空)
【蓝凌 / 新版 notifybus】
KEYVALUE
codeNamesuccess
msgNamemsg
dataName(留空)
successCodetrue
xmlJsonField(留空)
【蓝凌 / 旧版 sendTodo】
KEYVALUE
codeNamereturnState
msgNamemessage
dataNamedata
successCode2
xmlJsonField(留空)
【致远 / 主流返回】
KEYVALUE
codeNamesuccess
msgNameerrorMsgs
dataName(留空)
successCodetrue
xmlJsonField(留空)
【致远 / errcode 返回】
KEYVALUE
codeNameerrcode
msgNameerrmsg
dataNamedata
successCode200
xmlJsonField(留空)
【云之家 / 标准返回】
KEYVALUE
codeNamesuccess
msgNameerror
dataNamedata
successCodetrue
xmlJsonField(留空)
【云之家 / 不解析返回】
KEYVALUE
codeName(留空)
msgName(留空)
dataName(留空)
successCode(留空)
xmlJsonField(留空)
  1. codeName / msgName 支持 $. 开头的 JSONPath;线上有用 $.data.operResult、$.data.message 的写法,按实际返回层级选。
  2. successCode 前后不要有空格或制表符;线上出现过填成“\t 2”导致全部判失败的案例。
  3. 返回体把业务码包在 message 或 data 下时,codeName 要写完整路径,不能只写叶子字段。
  4. xmlJsonField 一般留空;只有 OA 返回 XML 且需要转 JSON 时,才按接口文档填写。
  5. 保存后先发一条真实请求,在同步日志里看返回体,再回头校准这五行。

0.1.4 函数参数配置

页面底部只有一项「函数参数」;未配置时显示“未设置”,右侧是「重新设置」按钮。这一步用来挂接 APL 函数。
页面字段页面显示操作
函数参数未设置点「重新设置」,关联 oaRequest 和 dataDetail
  1. 点击「重新设置」。
  2. 按页面提示关联请求前处理函数 oaRequest,以及免登函数 dataDetail;函数按各系统章节创建。
  3. 本文两个函数都没有入参,函数参数可以保持未设置;只有函数本身声明了参数时,才按参数名逐个填写。
  4. 保存后重新打开连接配置,确认函数参数区域不再显示“未设置”,且两个函数的类型正确。
函数类型作用不挂的后果
oaRequest / 请求前处理改写 requestData、url、header;云之家追加 accessToken,致远转换收件人和状态位云之家地址缺 token 或 401;致远报文字段不对
dataDetail / 免登用 ticket 换 OA 用户信息,返回 oaUser、redirectUrl点击待办免登失败或跳错页面
函数名和类型以页面下拉实际显示为准。各系统需要哪几个函数,见对应章节的“配套函数”小节。

0.2 三类事件与定位键

事件含义用哪个模板定位键要求
1 新增创建待办 / 提醒新增模板新增时写入,后续处理/删除必须能命中同一个键
2 处理办结、同意、拒绝处理模板与新增完全一致;状态位按系统调整
3 删除撤销待办删除模板与新增完全一致;部分系统用删除专用端点
消息提醒只发消息,不落待办crmNotify 新增模板没有处理/删除事件
最常见的问题不是字段写错,而是新增用一个键、处理或删除换成了另一个键。泛微的 flowid、蓝凌的 modelId/notifyId、致远的 taskId、云之家的 sourceId,都必须三事件一致。

0.3 本文占位符

占位符替换为示例
<OA域名>OA 访问域名(含端口)oa.example.com:8080
<注册码>OA 侧注册的集成码OA 控制台生成
<syscode>OA 侧注册的系统标识fxiaoke / CRM / FXXK
<企业EI>CRM 企业 ID在 CRM 企业信息中查看
<appId> / <appSecret>OA 应用凭证OA 后台应用管理
<tenantKey>云之家 / eteams 租户标识云之家后台
<Basic认证串>蓝凌 OpenAPI Basic 认证串蓝凌后台生成
<对象API> / <数据ID>CRM 回调路径中的对象与记录AccountObj / 5f...

一、泛微配置块

泛微有四条落地路线:标准接口(最常用)、预置接口、E10 新开放平台、消息中心。先按 1.2 选定一条路线,再整套复制该路线的新增/处理/删除模板,不要跨路线混用字段。

1.1 连接配置(页面字段)

页面字段推荐值说明
OA 类型泛微
连接地址https://<OA域名>带端口时一并填写
HeaderContent-Type: application/json部分 OA 另加 accept: */*、connection: Keep-Alive
结果解析operResult / message / 1如接口以 HTTP 200 判成功,successCode 改为 200
dataName留空
账号绑定字段OA 工号(loginid / workcode)与 receiver 占位符口径一致
不绑定不发送开启避免未绑定人员报错
函数oaRequest + dataDetailoaRequest 处理请求体;dataDetail 处理免登

1.2 路线选择

路线端点适用特点
标准接口/rest/ofs/ReceiveRequestInfoByJson大多数 E9三事件共用端点;处理改 isremark + viewtype
标准接口删除/rest/ofs/deleteUserRequestInfoByJson 或 /rest/ofs/deleteRequestInfoByJson对应 OA 版本只传 syscode + flowid(部分版本加 userid)
预置接口/rest/ofs/fxiaokeReceiveRequestInfoByJson已部署纷享预置包的 OA用 type 区分对象;删除加 ifdelete
E10/papi/openapi/api/open_intunifytodo/server_engine/receiveRequestInfo泛微 E10三事件同端点;删除 isremark 4
消息中心/papi/openapi/api/mc/msg/sendMsg只要提醒、不落待办仅 crmNotify;没有处理/删除

1.3 标准接口模板(最常用)

以下模板来自线上标准接口连接,已脱敏。pcurl / appurl 可以写相对路径(OA 侧已做 SSO 包装),也可以写 CRM 免登回调;两种都用同一套业务字段。

1.3.1 审批待办 ApprovalTaskObj

新增:
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "CRM-#F055-#F053-#F056", "workflowname": "#F056", "nodename": "#F026", "pcurl": "/xv/ui/detail?apiname=#F037&id=#F015", "appurl": "/hcrm/avah5#/object_detail/object_detail/pages/detail/index?apiName=#F037&dataId=#F015", "creator": "#F040", "createdatetime": "#F009", "receiver": "#F001", "receivedatetime": "#F009", "isremark": "0", "viewtype": "0", "receivets": "#currentTime#" }
处理:新增模板不变,只改 isremark 和 viewtype。
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "CRM-#F055-#F053-#F056", "workflowname": "#F056", "nodename": "#F026", "pcurl": "/xv/ui/detail?apiname=#F037&id=#F015", "appurl": "/hcrm/avah5#/object_detail/object_detail/pages/detail/index?apiName=#F037&dataId=#F015", "creator": "#F040", "createdatetime": "#F009", "receiver": "#F001", "receivedatetime": "#F009", "isremark": "2", "viewtype": "1", "receivets": "#currentTime#" }
删除(独立端点):
{ "syscode": "<syscode>", "flowid": "#F012" }
定位键:flowid 三事件必须一致。线上有租户用任务 ID #F012,也有租户用单据 ID #F015;选哪个都可以,但新增、处理、删除必须同一个。

1.3.2 新 BPM 待办 BpmTask

新增:
{ "syscode": "<syscode>", "flowid": "#G005", "requestname": "【CRM待办】-#G024 -#G051", "creator": "#G036", "receiver": "#F001", "workflowname": "#G021", "nodename": "#G022", "pcurl": "/<企业EI>/#G047/#G050/false", "appurl": "https://<OA域名>/sso/oauth2.0/authorize?client_id=<appId>&response_type=code&redirect_uri=https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/true", "viewtype": "0", "receivedatetime": "#G012", "isremark": "0", "createdatetime": "#G012" }
处理:
{ "syscode": "<syscode>", "flowid": "#G005", "requestname": "【CRM待办】-#G024", "creator": "#G036", "receiver": "#F001", "workflowname": "#G021", "nodename": "#G022", "viewtype": "1", "receivedatetime": "#G012", "isremark": "2" }
删除:
{ "userid": "#F001", "syscode": "<syscode>", "flowid": "#G005" }
线上 BpmTask 常用 #G005(节点实例 ID)做 flowid;如果同一节点有多个并行任务,改用任务 ID #G023 更稳,但三事件要一起改。接收人统一用 #F001,线上对所有任务对象都这么配。

1.3.3 阶段任务 StageTaskObj

新增:
{ "syscode": "<syscode>", "flowid": "#ST044", "requestname": "【CRM阶段任务】-#ST004-#ST041", "creator": "#ST017", "receiver": "#F001", "workflowname": "#ST041", "nodename": "#ST004", "pcurl": "/<企业EI>/#ST038/#ST006/false", "appurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/true", "viewtype": "0", "receivedatetime": "#ST022", "isremark": "0", "createdatetime": "#ST022" }
处理:
{ "syscode": "<syscode>", "flowid": "#ST044", "requestname": "【CRM阶段任务】-#ST004-#ST041", "creator": "#ST017", "receiver": "#F001", "workflowname": "#ST041", "nodename": "#ST004", "pcurl": "/<企业EI>/#ST038/#ST006/false", "appurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/true", "viewtype": "1", "receivedatetime": "#ST022", "isremark": "2" }
删除:
{ "userid": "#F001", "syscode": "<syscode>", "flowid": "#ST044" }
线上有租户删除时用了另一唯一键(如 #ST012),导致处理/删除命中不到新增。建议统一用任务 ID #ST044;如果 OA 侧要求别的键,三事件一起换。

1.3.4 消息提醒 crmNotify

{ "syscode": "<syscode>", "flowid": "#H005-#H001", "requestname": "【CRM提醒】-#H002", "nodename": "#H006", "receiver": "#H001", "workflowname": "#H006", "viewtype": "0", "creator": "#H001", "isremark": "0", "createdatetime": "#currentTime#", "receivedatetime": "#currentTime#", "pcurl": "/<企业EI>/#H003/#H005/false", "appurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/true" }
注意:标准接口这条模板会生成一条待办。如果只要提醒、不进待办列表,改用消息中心路线,或确认 OA 支持 isremark 8。

1.4 预置接口模板

预置接口用 type 区分对象类型,新增/处理/删除共用一个端点。线上 type 的用法是:1 审批任务、2 BPM 任务、3 阶段任务、4 工单。
新增(审批任务 type=1):
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "#F056", "workflowname": "#F055", "nodename": "#F026", "pcurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "appurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/true", "approval": "#F012", "dataid": "#F015", "objectname": "#F037", "approvalcode": "#F013", "creator": "#F049", "createdatetime": "#F009", "receiver": "#F001", "receivedatetime": "dateTime(#currentTime#)", "isremark": "0", "viewtype": "0", "type": "1", "receivets": "#currentTime#" }
处理:只改 isremark=2,viewtype 保持 0。
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "#F056", "workflowname": "#F055", "nodename": "#F026", "pcurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "appurl": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/true", "approval": "#F012", "dataid": "#F015", "objectname": "#F037", "approvalcode": "#F013", "creator": "#F049", "createdatetime": "#F009", "receiver": "#F001", "receivedatetime": "dateTime(#currentTime#)", "isremark": "2", "viewtype": "0", "type": "1", "receivets": "#currentTime#" }
删除:isremark 保持 0,加 ifdelete=1。
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "#F056", "workflowname": "#F055", "nodename": "#F026", "receiver": "#F001", "isremark": "0", "viewtype": "0", "type": "1", "ifdelete": "1", "receivets": "#currentTime#" }
对象typeflowid 建议requestname 建议
ApprovalTaskObj 审批任务1#F012#F056
BpmTask 新 BPM 任务2#G023#G024
StageTaskObj 阶段任务3#ST044#ST041
CasesObj 工单4#C032#C022
线上有些预置接口删除模板写 isremark=4,有些写 0 + ifdelete=1。两种都能见到;以 OA 侧预置包版本为准,但新增/处理/删除的 flowid 必须一致。

1.5 E10 开放平台模板

新增:
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "#F055", "workflowcode": "#F050", "workflowname": "#F055", "receivernodename": "#F026", "nodename": "#F026", "pcurl": "/<企业EI>/#F037/#F015/false", "appurl": "/<企业EI>/#F037/#F015/false", "creator": "#F040", "createdatetime": "#F009", "receiver": "#F001", "receivedatetime": "#currentTime#", "isremark": "0", "viewtype": "0", "receivets": "" }
处理:
{ "syscode": "<syscode>", "flowid": "#F012", "requestname": "#F055", "workflowcode": "#F050", "workflowname": "#F055", "receivernodename": "#F026", "nodename": "#F026", "creator": "#F040", "createdatetime": "#F009", "receiver": "#F001", "receivedatetime": "#currentTime#", "isremark": "2", "viewtype": "1", "receivets": "" }
删除:
{ "syscode": "<syscode>", "flowid": "#F012", "receiver": "#F001", "isremark": "4", "viewtype": "0", "receivets": "" }
线上 E10 删除用的是 isremark 4,不是 -1。只有 OA 版本明确要求 -1 时才改;三事件的 viewtype 建议保持一致,处理时可用 1。

1.6 配套函数

连接里通常挂两个函数:oaRequest 处理请求体(可选,但线上普遍使用),dataDetail 处理免登。泛微的 token 获取放在 dataDetail。

1.6.1 oaRequest:请求体二次处理

// 函数类型:oaRequest // 作用:只处理 requestData,不修改 URL Map requestData = Fx.json.parse(syncArg["requestData"] as String) String workflowname = requestData["workflowname"] as String String nodename = requestData["nodename"] as String if ((workflowname != null && workflowname.contains("【作废】")) || (nodename != null && nodename.contains("【作废】"))) { log.info("命中作废关键字,跳过同步") return null } if (requestData["createdatetime"] == "#createdatetime") { requestData.put("createdatetime", DateTime.now() as String) } if (requestData["receivedatetime"] == "#receivedatetime") { requestData.put("receivedatetime", DateTime.now() as String) } syncArg.put("requestData", Fx.json.toJson(requestData)) return syncArg
如果 BpmTask 的 pcurl 指向任务本身而不是业务单据,可以在这个函数里先查 BpmTask,再把 pcurl 改写成业务对象的 API 名和数据 ID。线上有租户这么做;没有这个问题就保持上面的精简版。

1.6.2 dataDetail:免登

// 函数类型:dataDetail Map requestParams = syncArg["params"]["requestParams"] as Map String apiName = requestParams["apiName"] as String String dataId = requestParams["dataId"] as String boolean isApp = requestParams["isApp"] as boolean String ticketCode = requestParams["ticket"] as String String PREFIX_URL = "https://<OA域名>/" String CLIENTID = "<appId>" String CLIENTSECRET = "<appSecret>" String redirect_uri = "https://www.fxiaoke.com/oauth/sp/callback" if (!apiName) { String home = isApp ? "https://www.fxiaoke.com/hcrm/avah5" : "https://www.fxiaoke.com/XV/UI/Home#crm/index" syncArg.put("redirectUrl", home) return syncArg } String tokenUrl = PREFIX_URL + "sso/oauth2.0/accessToken?client_id=" + CLIENTID + "&client_secret=" + CLIENTSECRET + "&code=" + ticketCode + "&grant_type=authorization_code&redirect_uri=" + redirect_uri def (Boolean error, HttpResult data, String errorMessage) = Fx.http.post(tokenUrl, [:], [:]) if (error) { message.throwErrorMessage("获取OA token失败:" + errorMessage) } Map result = Fx.json.parse(data.content as String) String accessToken = result.access_token as String HttpResult userData = (HttpResult) http.get( PREFIX_URL + "sso/oauth2.0/profile?access_token=" + accessToken, ["access_token": accessToken]).getData() String oaLoginId = userData.content["attributes"]["loginid"].toString() def (Boolean error1, QueryResult dataU, String errorMessage1) = Fx.object.find( "PersonnelObj", FQLAttribute.builder() .columns(["_id", "name", "employee_number", "user_id", "field_<绑定字段>__c"]) .queryTemplate(QueryTemplate.AND([ "field_<绑定字段>__c": QueryOperator.EQ(oaLoginId)])) .build(), SelectAttribute.builder().needInvalid(false).build() ) if (dataU.size > 0) { Map person = (dataU.dataList as List)[0] as Map syncArg.put("oaUser", person["field_<绑定字段>__c"].toString()) } else { message.throwErrorMessage("找不到对应的CRM人员:" + oaLoginId) } return syncArg

1.7 泛微验收与常见错误

现象优先检查
平台显示成功,OA 没有待办flowid 是否为空;receiver 是否绑定;OA 返回码是否被 resultFormat 判成成功
处理/删除无效三事件 flowid 是否一致;标准接口处理是否把 viewtype 从 0 改成 1
待办重复flowid 是否每条都唯一;重试是否重复消费
免登打不开dataDetail 是否挂上;pcurl/appurl 是否指向正确对象和数据 ID
401 / URL 参数重复函数是否重复追加 token 或地址参数
找不到用户PersonnelObj 绑定字段是否与 OA 返回的 loginid 一致

二、蓝凌配置块

蓝凌有两代接口:新版 notifybus(send / done / removeTodo,推荐)和旧版 sysNotifyTodoRestService(sendTodo / setTodoDone / deleteTodo,存量客户常见)。先确认 OA 部署的是哪一代,再整套复制。

2.1 连接配置(页面字段)

页面字段新版 notifybus旧版 sendTodo
OA 类型蓝凌蓝凌
连接地址https://<蓝凌域名>https://<蓝凌域名>
HeaderContent-Type: application/json;Authorization: Basic <Basic认证串>Content-Type: application/json;部分部署无需鉴权
结果解析success / msg / truereturnState / message / 2
dataName留空留空
账号绑定字段LoginNameLoginName 或 PersonNo
函数dataDetaildataDetail
线上新版连接通常没有 oaRequest;如果要在请求体里做工号转换或字段清洗,再额外加一个 oaRequest。

2.2 新版 notifybus 模板(推荐)

新增(审批任务):
{ "appName": "crm", "content": "#F004", "creator": {"fdLoginName": "admin", "fdOrgType": 8}, "entityId": "#F012", "entityKey": "crm", "entityName": "crm", "link": "https://<蓝凌域名>/data/sys-oauth/ssoLogin?appId=<appId>&redirection_url=https%3a%2f%2fwww.fxiaoke.com%2ferp%2fsyncdata%2fopen%2foa%2fauthorize%2fcommon%2flogin%3fei%3d<企业EI>%26apiName%3d#F037%26dataId%3d#F015", "mobileLink": "同 link", "moduleName": "crm", "notifyId": "#F012", "notifyType": "todo", "subject": "#F004", "targets": "{\"fdLoginName\":\"#F001\",\"fdOrgType\":8}" }
处理:
{ "appName": "crm", "entityId": "#F012", "entityKey": "crm", "entityName": "crm", "moduleName": "crm", "notifyId": "#F012", "targets": "{\"fdLoginName\":\"#F001\",\"fdOrgType\":8}", "timestamp": #currentTime# }
删除:
{ "appName": "crm", "entityId": "#F012", "entityKey": "crm", "entityName": "crm", "moduleName": "crm", "notifyId": "#F012", "targets": "{\"fdLoginName\":\"#F001\",\"fdOrgType\":8}", "timestamp": #currentTime# }
不同对象的替换关系:
对象entityId / notifyIdcontentsubjectlink 路径
ApprovalTaskObj#F012#F004#F004#F028/#F037/#F015
BpmTask#G023#G022#G021#G026/#G047/#G050
StageTaskObj#ST044#ST041#ST041#ST002/#ST038/#ST006
CasesObj#C032#C022#C022#C010/#C039/#C032
targets 是 JSON 字符串,不是对象;双引号要转义。线上最常见的失败就是 targets 写成对象,OA 侧解析不到接收人。

2.3 旧版 sendTodo 模板(存量)

新增:
{ "appName": "CRM", "modelName": "#F037", "modelId": "#F012-#F001", "subject": "#F055[#F053]#F056", "link": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "mobileLink": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/true", "padLink": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "type": 1, "targets": "{\"LoginName\":\"#F001\"}", "createTime": "dateTime(#currentTime#)" }
处理:
{ "appName": "CRM", "modelName": "#F037", "modelId": "#F012-#F001", "optType": 2, "targets": "{\"LoginName\":\"#F001\"}" }
删除:
{ "appName": "CRM", "modelName": "#F037", "modelId": "#F012-#F001", "optType": 1, "type": 1, "targets": "{\"LoginName\":\"#F001\"}" }
旧版线上常把接收人拼进 modelId(如 #F012-#F001),避免同一任务多人的待办互相覆盖。新版用 entityId/notifyId + targets,不需要拼接收人。

2.4 消息提醒 crmNotify(旧版)

{ "appName": "CRM", "modelName": "CRM_REMIND", "modelId": "#H005-#H001", "subject": "#H002", "content": "#H006", "type": 2, "targets": "{\"LoginName\":\"#H001\"}", "link": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/false", "mobileLink": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/true", "padLink": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/false", "createTime": "dateTime(#currentTime#)" }
modelName 按 OA 实际模型填写:线上有 CRM_REMIND,也有具体类名(如 KmReviewMain)。targets 可用 LoginName 或 PersonNo,和连接绑定字段保持一致。

2.5 配套函数 dataDetail

// 函数类型:dataDetail Map requestParams = syncArg["params"]["requestParams"] as Map String apiName = requestParams["apiName"] as String String dataId = requestParams["dataId"] as String boolean isApp = requestParams["isApp"] as boolean String code = requestParams["mkCode"] as String if (!code) { code = requestParams["code"] as String } String oaBaseUrl = "https://<蓝凌域名>" String appId = "<appId>" String appSecret = "<appSecret>" Map<String, String> oaHeaders = [ "Content-Type": "application/json", "Authorization": "Basic <Basic认证串>" ] String oaUser = null if (!apiName) { String home = isApp ? "https://www.fxiaoke.com/hcrm/avah5" : "https://www.fxiaoke.com/XV/UI/Home#crm/index" syncArg.put("redirectUrl", home) } if (code) { String tokenUrl = oaBaseUrl + "/openapi/sys-oauth/openOauth/getToken" Map<String, Object> tokenArg = ["appId": appId, "appSecret": appSecret, "code": code] def (Boolean tokenError, HttpResult tokenResult, String tokenMsg) = http.post(tokenUrl, oaHeaders, tokenArg) String token = null if (!tokenError && tokenResult != null && tokenResult.statusCode == 200) { Map tokenContent = tokenResult.content as Map if (tokenContent["success"] == true && tokenContent["data"] != null) { token = (tokenContent["data"] as Map)["token"] as String } } if (!token) { message.throwErrorMessage("蓝凌 getToken 失败:" + tokenMsg) } String userInfoUrl = oaBaseUrl + "/openapi/sys-oauth/openOauth/getUserInfo" Map<String, Object> userArg = ["token": token] as Map<String, Object> def (Boolean userError, HttpResult userResult, String userMsg) = http.post(userInfoUrl, oaHeaders, userArg) if (!userError && userResult != null && userResult.statusCode == 200) { Map userContent = userResult.content as Map if (userContent["success"] == true && userContent["data"] != null) { oaUser = (userContent["data"] as Map)["loginName"] as String } } if (!oaUser) { message.throwErrorMessage("蓝凌 getUserInfo 失败:" + userMsg) } } if (oaUser) { syncArg.put("oaUser", oaUser) } else { message.throwErrorMessage("未获取到 OA code,无法免登") } return syncArg

2.6 蓝凌验收与常见错误

现象优先检查
新增成功但接收人为空targets 是否为 JSON 字符串;LoginName/PersonNo 与绑定字段是否一致
处理/删除无效modelId/notifyId 是否与新增一致;新版是否用了 done/removeTodo 对应端点
平台成功但 OA 无待办resultFormat successCode 是否为 true(新版)或 2(旧版)
免登失败getToken/getUserInfo 的 appId、appSecret、Basic 串是否正确;code 参数名是 mkCode 还是 code
重复待办旧版 modelId 是否包含接收人;新版 notifyId 是否唯一

三、致远配置块

致远线上把 taskId 后缀、动作映射、状态更新都放在 oaRequest 函数里;模板只写基础字段。复制时一定要把模板和函数一起复制,不能只复制模板。

3.1 连接配置(页面字段)

页面字段推荐值说明
OA 类型致远
连接地址https://<OA域名>带端口时一并填写
HeaderContent-Type: application/json线上也有留空仍可用的部署
结果解析errcode / errmsg / 200dataName 可填 data
账号绑定字段OA 工号(employee_number)函数会把 user_id 转工号
不绑定不发送开启线上多数连接开启
函数oaRequest + dataDetailoaRequest 负责发送/更新/消息;dataDetail 负责免登

3.2 审批待办 ApprovalTaskObj

新增:
{ "registerCode": "<注册码>", "taskId": "#F012", "title": "#F056", "senderName": "#F040", "classify": "CRM", "state": "0", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/true", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "noneBindingSender": "#F040", "noneBindingReceiver": "#F001", "objectId": "#F015", "entityId": "#F037" }
处理:state=1,带 action,flagTax 触发更新。
{ "registerCode": "<注册码>", "taskId": "#F012", "title": "#F056", "senderName": "#F040", "classify": "CRM", "state": "1", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "noneBindingSender": "#F040", "noneBindingReceiver": "#F001", "action": "#F061", "objectId": "#F015", "flagTax": "U", "entityId": "#F037" }
删除:state=1,subState=2。
{ "registerCode": "<注册码>", "taskId": "#F012", "title": "#F056", "senderName": "#F040", "classify": "CRM", "state": "1", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/false", "noneBindingSender": "#F040", "noneBindingReceiver": "#F001", "subState": "2", "objectId": "#F015", "entityId": "#F037" }

3.3 新 BPM 待办 BpmTask

新增:
{ "registerCode": "<注册码>", "taskId": "#G023", "title": "#G021", "senderName": "#G036", "classify": "CRM", "state": "0", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/true", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/false", "noneBindingSender": "#G036", "noneBindingReceiver": "#F001", "objectId": "#G050", "entityId": "#G047" }
处理:
{ "registerCode": "<注册码>", "taskId": "#G023", "title": "#G021", "senderName": "#G036", "classify": "CRM", "state": "1", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/true", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/false", "noneBindingSender": "#G036", "noneBindingReceiver": "#F001", "action": "#G019", "objectId": "#G050", "flagTax": "U", "entityId": "#G047" }
删除:
{ "registerCode": "<注册码>", "taskId": "#G023", "title": "#G021", "senderName": "#G036", "classify": "CRM", "state": "1", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/false", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#G047/#G050/false", "noneBindingSender": "#G036", "noneBindingReceiver": "#F001", "subState": "2", "objectId": "#G050", "entityId": "#G047" }
线上有模板把 BpmTask 的 objectId/entityId 写成 #F015/#F037,会导致关联对象不准;按对象换成 #G050/#G047。

3.4 阶段任务 StageTaskObj

新增:
{ "registerCode": "<注册码>", "taskId": "#ST044", "title": "#ST041", "senderName": "#ST017", "classify": "CRM", "state": "0", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/true", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/false", "noneBindingSender": "#ST017", "noneBindingReceiver": "#F001", "objectId": "#ST006", "entityId": "#ST038" }
处理:
{ "registerCode": "<注册码>", "taskId": "#ST044", "title": "#ST041", "senderName": "#ST017", "classify": "CRM", "state": "1", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/true", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/false", "noneBindingSender": "#ST017", "noneBindingReceiver": "#F001", "flagTax": "U", "objectId": "#ST006", "entityId": "#ST038" }
删除:
{ "registerCode": "<注册码>", "taskId": "#ST044", "title": "#ST041", "senderName": "#ST017", "classify": "CRM", "state": "1", "thirdReceiverId": "#F001", "creationDate": "#currentTime#", "h5url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/false", "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#ST038/#ST006/false", "noneBindingSender": "#ST017", "noneBindingReceiver": "#F001", "subState": "2", "objectId": "#ST006", "entityId": "#ST038" }

3.5 消息提醒 crmNotify

{ "thirdpartyRegisterCode": "<消息注册码>", "thirdpartyMessageId": "#H004", "messageContent": "#H006", "thirdpartySenderId": "#H001", "thirdpartyReceiverId": "#H001", "messageH5URL": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/true", "messageURL": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/false", "noneBindingSender": "#H001", "noneBindingReceiver": "#H001" }
致远的消息和待办是两个端点:待办走 thirdpartyPending,消息走 thirdpartyMessage/singleMessage。消息模板里的注册码通常与待办注册码分开申请。

3.6 配套函数 oaRequest

这个函数是致远配置的核心:消息分支、工号转换、action 映射、taskId 后缀、状态更新都在这里。模板里的 taskId 只写原始任务 ID,函数会追加“-接收人”,保证一人一条。
// 函数类型:oaRequest Map requestData = Fx.json.parse(syncArg["requestData"] as String) as Map Map headerMap = syncArg["header"] as Map String url = syncArg["url"] as String // 1. 消息提醒:直接调消息接口 String thirdpartyRegisterCode = requestData["thirdpartyRegisterCode"] as String if (thirdpartyRegisterCode != null) { requestData["creation_date"] = DateTime.now() as String String messageH5URL = requestData["messageH5URL"] as String if (messageH5URL != null && messageH5URL.contains("<企业EI>//")) { requestData["messageH5URL"] = messageH5URL.replace("<企业EI>//", "<企业EI>/<消息回调标识>/") } String messageURL = requestData["messageURL"] as String if (messageURL != null && messageURL.contains("<企业EI>//")) { requestData["messageURL"] = messageURL.replace("<企业EI>//", "<企业EI>/<消息回调标识>/") } Map oaResult = OABPMUtilsPro.messageTodo(requestData) return ["requestData": requestData, "header": headerMap, "url": url, "result": oaResult] } // 2. 发送人/接收人转 OA 工号 String senderName = covtStr(requestData["senderName"] as String) String thirdReceiverId = covtStr(requestData["thirdReceiverId"] as String) requestData["senderName"] = senderName requestData["thirdReceiverId"] = thirdReceiverId requestData["noneBindingSender"] = senderName requestData["noneBindingReceiver"] = thirdReceiverId // 3. 审批动作 → 致远 subState String action = requestData["action"] as String if (action) { switch (action) { case "cancel": break case "reject": requestData.put("subState", "1"); break case "agree": requestData.put("subState", "0"); break default: break } requestData.remove("action") } // 4. taskId 追加接收人,保证一人一条 String taskId = requestData["taskId"] as String requestData["taskId"] = taskId + "-" + thirdReceiverId // 5. 有 flagTax:走状态更新(处理/删除);否则新建 String flagTax = requestData["flagTax"] as String if (flagTax != null) { String subState = requestData["subState"] as String if (subState == null) { subState = (action == "agree") ? "0" : "1" } requestData.put("subState", subState) Map oaResult = OABPMUtils.updatePendingState(requestData) return ["requestData": requestData, "header": headerMap, "url": url, "result": oaResult] } Map oaResult = OABPMUtils.sendTodo(requestData) return ["requestData": requestData, "header": headerMap, "url": url, "result": oaResult] def String covtStr(String str) { String resultStr = str if (str != null && !str.contains("V")) { if (str.contains("[")) { str = str.replace("[", "").replace("]", "") as String } FQLAttribute fql = FQLAttribute.builder() .columns(["_id", "name", "user_id", "employee_number"]) .queryTemplate(QueryTemplate.AND(["user_id": QueryOperator.EQ(str)])) .build() def (Boolean error, Map data, String errorMessage) = Fx.object.findOne( "PersonnelObj", fql, SelectAttribute.builder().build()) resultStr = (data == null || data.size() == 0) ? str : data["employee_number"] as String if (data != null && data["employee_number"] == null) { resultStr = str } } return resultStr }
OABPMUtils / OABPMUtilsPro 是致远对接工具类,按当前环境实际类名替换。删除时如果 OA 要求 subState=2,模板里写上 subState,函数会保留传入值;线上部分旧函数会重算成 1,需要按这个版本修正。

3.7 配套函数 dataDetail

// 函数类型:dataDetail Map requestParams = syncArg["params"]["requestParams"] as Map String apiName = requestParams["apiName"] as String String dataId = requestParams["dataId"] as String boolean isApp = requestParams["isApp"] as boolean String ticket = requestParams["v5ticket"] as String String oaticket = requestParams["oaticket"] as String if (oaticket) { syncArg.put("oaUser", oaticket) return syncArg } String redirectUrl if (!apiName || apiName == "" || apiName.contains("<消息回调标识>") || apiName.contains("H003")) { redirectUrl = isApp ? "https://www.fxiaoke.com/hcrm/avah5" : "https://www.fxiaoke.com/XV/UI/Home#crm/index" syncArg.put("redirectUrl", redirectUrl) } String userId = OABPMUtils.ticket(ticket) syncArg.put("oaUser", userId) return syncArg

3.8 致远验收与常见错误

现象优先检查
新增成功但处理无效taskId 是否由同一个函数追加了相同接收人后缀
多人收到同一条待办taskId 是否追加了 thirdReceiverId;函数是否启用
删除后仍显示待办删除模板是否带 subState=2;flagTax 是否触发 updatePendingState
发送人/接收人为空covtStr 是否把 user_id 转成 employee_number;PersonnelObj 是否有工号
消息发不出是否走了 thirdpartyMessage 端点;消息注册码是否正确
平台成功但 OA 无数据resultFormat errcode/200 是否与 OA 返回一致;函数是否返回了 result

四、云之家配置块

云之家 token 由 oaRequest 获取:场景 URL 末尾保留 ?accessToken=,由 oaRequest 调用 YZJService.getAppToken() 追加;连接页面不保存 appSecret。

4.1 连接配置(页面字段)

页面字段推荐值说明
OA 类型云之家
连接地址https://<云之家域名>标准云之家为 https://www.yunzhijia.com
HeaderContent-Type: application/json
结果解析errorCode / error / 200
dataName留空
账号绑定字段云之家 openId与 params[].openId、openids 一致
不绑定不发送开启
函数oaRequest + dataDetailoaRequest 追加 token;dataDetail 换 openId
新增/处理/删除的 URL 都以 ?accessToken= 结尾,不要手动填 token;函数会在请求前拼上。

4.2 待办模板(审批 / BPM / 阶段任务)

审批待办新增:
{ "content": "#F056 ->单据号:#F053,提交人:#F054", "title": "#F055", "itemtitle": "#F056", "headImg": "https://<云之家域名>/space/c/photo/load?id=<默认头像ID>", "appId": "<appId>", "senderId": "#F049", "todoType": "1", "params": [{"openId": "#F001"}], "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#F037/#F015/true", "sourceId": "#F012-#F001", "sync": true }
处理:
{ "sourceitemid": "#F012-#F001", "sourcetype": "<appId>", "actiontype": {"deal": 1}, "openids": ["#F001"], "sync": true }
删除:
{ "sourceitemid": "#F012-#F001", "sourcetype": "<appId>", "actiontype": {"delete": 1}, "openids": ["#F001"], "sync": true }
不同对象的替换关系:
对象sourceIdtitleitemtitlecontenturl 路径
ApprovalTaskObj#F012-#F001#F055#F056#F056 / #F053 / #F054#F028/#F037/#F015
BpmTask#G023-#F001#G021#G024提交人:#G051#G026/#G047/#G050
StageTaskObj#ST044-#F001#ST004#ST041#ST041#ST002/#ST038/#ST006
CasesObj#C032-#F001#C004#C022#C022#C010/#C039/#C032
sourceId 必须三事件一致:新增写进 sourceId,处理和删除用 sourceitemid 回指,sourcetype 回指 appId。线上有租户用 #ST041、#ST043 做阶段任务 sourceId,建议统一用任务 ID #ST044,避免同名任务冲突。

4.3 消息提醒模板

方式一:generatetodo 发消息(线上常用):
{ "type": "message", "msgType": "#H007", "content": "#H006", "title": "#H002", "feedid": #H010, "headImg": "https://<云之家域名>/space/c/photo/load?id=<默认头像ID>", "appId": "<appId>", "todoType": "0", "params": [{"openId": "#H001"}], "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/true", "sourceId": "#H005-#H004", "sync": true }
方式二:云之家 pubacc/pubsend(部分部署):
{ "type": "message", "content": "#H002-#H006", "title": "#H002", "appId": "<appId>", "todoType": "0", "noticeType": #H011, "params": [{"openId": "#H001"}], "url": "https://www.fxiaoke.com/erp/syncdata/open/oa/authorize/common/<企业EI>/#H003/#H005/true", "sourceId": "#H005", "sync": true }
feedid 用结构化占位符 #H010(不加引号),用于 @me / feed 深链;如果模板里写成字符串 "#H010",拿到的是字面量而不是消息 JSON。

4.4 配套函数 oaRequest

// 函数类型:oaRequest Map requestData = Fx.json.parse(syncArg["requestData"] as String) if (requestData["url"]) { String reqUrl = requestData["url"] as String if (reqUrl.contains("#H003")) { requestData["url"] = reqUrl.replace("#H003", "H003") } } String msgType = requestData["msgType"] as String if (msgType && msgType == "text") { requestData.remove("url") } syncArg.put("requestData", Fx.json.toJson(requestData)) String url = syncArg["url"] as String String accessToken = YZJService.getAppToken() syncArg.put("url", url + accessToken) return syncArg
线上这个函数直接修改 syncArg["url"],所以场景 URL 必须预留 ?accessToken=,否则 token 没有位置追加。

4.5 配套函数 dataDetail

// 函数类型:dataDetail String userAgent = syncArg["params"]["headers"]["user-agent"] as String String apiName = syncArg["params"]["requestParams"]["apiName"] as String String dataId = syncArg["params"]["requestParams"]["dataId"] as String Map requestParams = syncArg["params"]["requestParams"] as Map boolean apiNameIsEmpty = (apiName == null || apiName == "" || apiName == "null") def mobilePattern = /Mobile|iPad|iPhone|Android|BlackBerry|Windows Phone|webOS/ def isMobile = (userAgent =~ mobilePattern).find() boolean fromCrmMessage = requestParams.containsKey("crm_msg") String redirectUrl if (!fromCrmMessage && !apiNameIsEmpty) { redirectUrl = isMobile ? "https://www.fxiaoke.com/hcrm/avah5#/uipaas_custom/object_detail/pages/detail/index?apiName=" + apiName + "&dataId=" + dataId : "https://www.fxiaoke.com/XV/UI/Home#paasapp/detail/=/appId_CRM/" + apiName + "/" + dataId } else { redirectUrl = isMobile ? "https://www.fxiaoke.com/hcrm/avah5" : "https://www.fxiaoke.com/XV/UI/Home#paasapp/remind/405/=/appId_CRM" } syncArg.put("redirectUrl", redirectUrl) String ticket = requestParams["ticket"] as String String openid = YZJService.getTicketOpenid(ticket) syncArg.put("oaUser", openid) return syncArg

4.6 云之家验收与常见错误

现象优先检查
401 / token 无效场景 URL 是否以 ?accessToken= 结尾;oaRequest 是否已挂载;YZJService 是否可用
处理/删除无效sourceitemid 是否等于新增 sourceId;sourcetype 是否等于新增 appId
接收人收不到params[].openId / openids 是否为云之家 openId;账号绑定字段是否一致
文本消息报错函数是否在 msgType=text 时删除 url
@me 拿不到 feedIdfeedid 是否用结构化 #H010;消息模板是否带 origin
多人待办互相覆盖sourceId 是否包含接收人,#F001

五、横向速查

5.1 三事件状态位

系统 / 路线新增处理删除定位键
泛微 标准接口isremark 0,viewtype 0isremark 2,viewtype 1deleteUserRequestInfoByJson / deleteRequestInfoByJsonflowid
泛微 预置接口isremark 0,type 1-4,viewtype 0isremark 2,viewtype 0isremark 0 + ifdelete 1flowid
泛微 E10isremark 0,viewtype 0isremark 2,viewtype 1isremark 4,viewtype 0flowid
蓝凌 新版senddoneremoveTodoentityId / notifyId
蓝凌 旧版sendTodosetTodoDone optType 2deleteTodo optType 1modelId
致远state 0state 1 + action + flagTaxstate 1 + subState 2taskId(函数追加 -接收人)
云之家generatetodo,todoType 1action.json deal 1action.json delete 1sourceId → sourceitemid

5.2 令牌表

审批待办 ApprovalTaskObj(#F0xx):
令牌字段 API 名含义
#F001candidate_ids任务待处理人(所有任务对象模板里都用作接收人)
#F004name任务主题
#F009create_time创建时间
#F012_id任务 ID(常用定位键)
#F013activity_id节点 ID
#F015object_data_id单据 ID
#F022personhandler处理人(部分 OA 模板使用)
#F023creator创建人(部分 OA 模板使用)
#F026task_name任务名称
#F028tenant_id企业 ID(回调路径使用)
#F037object_api_name对象 API 名
#F040owner负责人
#F045workflow_instance_id流程实例 ID
#F049submitter提交人
#F050workflow_code流程编码(E10 模板使用)
#F053object_data_id__r单据名称
#F054submitter__r提交人姓名
#F055object_api_name__r对象中文名
#F056workflow_instance_id__r流程标题
#F061action审批动作(agree / reject / cancel)
#F062reply_user审批人
#F063 / #F064approval_time审批时间
新 BPM 待办 BpmTask(#G0xx):
令牌字段 API 名含义
#G004activityId节点 ID
#G005activity_instance_id节点实例 ID(线上常用作 flowid)
#G009applicantId申请人
#G012create_time创建时间
#G019action_code操作码(线上用作 action)
#G021name任务主题
#G022taskName任务名称
#G023_id任务 ID(推荐定位键)
#G024workflowInstanceName流程主题
#G026tenant_id企业 ID
#G027objectIds单据 ID 集合
#G029stageName阶段名
#G031objectApiName对象 API 名(部分模板使用)
#G036owner负责人
#G040record_type记录类型
#G044current_candidate_ids当前待处理人
#G047objectApiName对象 API 名
#G050objectDataId单据数据 ID
#G051owner__r处理人姓名
#G052nodeObjectId节点流转对象 ID(部分模板使用)
阶段任务 StageTaskObj(#ST0xx):
令牌字段 API 名含义
#ST002tenant_id企业 ID
#ST004workflow_name流程名
#ST006object_data_id关联单据 ID
#ST017created_by_name创建人 / 发起人(线上作 senderName)
#ST019last_modified_time最后修改时间
#ST022create_time创建时间
#ST030created_by创建人
#ST038object_api_name对象 API 名
#ST039current_candidate_ids当前待处理人
#ST041name任务名称
#ST043order_by排序值(部分线上模板用作 sourceId,需确认唯一)
#ST044_id任务 ID(推荐定位键)
消息对象 crmNotify(#H0xx):
令牌字段 API 名含义
#H001receiverId接收人
#H002title标题
#H003objectApiName对象 API 名
#H004workflowInstanceId流程实例 ID
#H005objectId对象数据 ID
#H006messageContent消息正文
#H007type消息类型(card / text)
#H009enterpriseId企业 ID
#H010origin原始消息 JSON(取 feedId / 深链用)
#H011noticeType通知类型(部分 OA 使用)

5.3 结果解析与账号绑定

系统 / 路线codeNamemsgNamesuccessCode账号绑定字段
泛微operResultmessage1OA 工号 loginid
蓝凌 新版successmsgtrueLoginName
蓝凌 旧版returnStatemessage2LoginName / PersonNo
致远errcodeerrmsg200employee_number
云之家errorCodeerror200openId

5.4 上线核对清单

  1. 连接页面不配置动态 URL / token,secret 没有写在页面或模板里,动态逻辑都在 oaRequest。
  2. 函数参数配置已关联 oaRequest 和 dataDetail,页面不再显示“未设置”。
  3. 连接结果解析的 codeName / msgName / successCode 与 OA 实际返回一致,successCode 没有前后空格。
  4. 账号绑定字段与模板里的接收人占位符口径一致(工号 / LoginName / openId)。
  5. 新增、处理、删除三事件的定位键完全一致。
  6. 泛微处理事件已把 viewtype 从 0 改成 1(标准接口)。
  7. 蓝凌 targets 是 JSON 字符串,不是对象。
  8. 致远 oaRequest 已启用,taskId 会追加“-接收人”。
  9. 云之家场景 URL 以 ?accessToken= 结尾,oaRequest 已追加 token。
  10. 函数日志里能看到每次请求的 requestData 和 OA 返回,且没有敏感信息。
  11. 用一条真实待办走完新增 → 处理 → 删除,再检查 OA 当前状态。

六、版本与来源说明

本文于 2026-10-23 依据线上正在运行的泛微、蓝凌、致远、云之家 OA 待办连接器整理:连接参数、场景模板和当前生效的 APL 函数均做过脱敏,不包含客户域名、注册码、appId、secret、企业 EI 或人员信息。本文是线上配置的总结,暂未逐项经过真实 OA 系统联调校验。
线上配置会随 OA 版本、租户定制和接口升级变化。复制模板后,请以该 OA 的实际接口文档和一条真实数据的返回为准;如果 OA 侧升级了端点或状态位,优先按 OA 文档调整,不要照搬旧模板。
2026-10-23
0 0