泛微二开标准代码模板

E9

前端

触发时机

jQuery

1
2
//页面挂载触发
$(document).ready(function () {})

JS原生

1
2
3
4
5
6
//dom挂载触发
document.addEventListener('DOMContentLoaded'function)
//hash路径变化触发
window.addEventListener('hashchange'function)
// 监听页面可见性变化
document.addEventListener("visibilitychange"function);

限定范围

ecodeSDK.checkLPath

1
2
3
if (ecodeSDK.checkLPath('/spa/workflow/static4form/index.html')) {
console.log(' XXX 代码开始执行')
}

JS原生

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//全路径
window.location.pathname === '/sp/integration/loginSingle/freepass'
//路径包含
window.location.href.includes('/workflow/request/')
//正则匹配
if (
/#\/main\/workflow\/req\?([^&]*&)*workflowid=42441(&|$)/.test(location.href)
) {
console.log('【retrieve-from-report】 触发')
}
//哈希包含
if (
window.location.hash.includes(
'#/main/workflow/req?iscreate=1&workflowid=37502'
)
) {
console.log('逻辑触发')
}

组件复写

1
2
3
4
5
6
7
ecodeSDK.overwritePropsFnQueueMapSet('WeaTop', {
fn: (newProps) => {
console.log('拦截到目标组件,参数:', newProps)
},
order: 1,
desc: ' XXX 组件重写',
})

拦截WeaTop加按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ecodeSDK.overwritePropsFnQueueMapSet('WeaTop', {
fn: (newProps) => {
if (newProps.ecId === '_Route@4q280c_WeaTop@c0nzkl') {
console.log('拦截到目标组件,参数:', newProps)
}
const { Button } = antd //自定义点击事件
const handleIndicatorClick = () => {
alert('按钮被点击')
}
const newButton = (
<Button type="primary" onClick={handleIndicatorClick}>
退回到提报人
</Button>
) //将新按钮插入到 buttons 数组的最前面
newProps.buttons = [newButton, ...newProps.buttons]
},
order: 1,
desc: '拦截到weatop,用于添加按钮',
})

组件重写

register.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const NewWeaTab = (props) => {
const acParams = {
appId: '${appId}',
name: 'NewWeaTabCom',
isPage: false,
noCss: true,
props,
}

const NewCom = props.Com
return window.comsMobx ? (
ecodeSDK.getAsyncCom(acParams)
) : (
<NewCom {...props} />
)
}

ecodeSDK.overwriteClassFnQueueMapSet('WeaTab', {
fn: (Com, newProps) => {
if (
!(
newProps.ecId ===
'_ListCell@cebo01_DropdownOverlay@fpgeqx_Tabs@abxotu_WeaTab@3x9y9h'
)
)
return
if (newProps._noOverwrite) return
return {
com: NewWeaTab,
props: newProps,
}
},
order: 1,
desc: 'WeaTab组件重写',
})

NewWeaTab.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
const { WeaTab } = ecCom
const { Modal, message } = antd

class NewWeaTabCom extends React.Component {
constructor(props) {
super(props)
this.state = {}
}

handleTabChange(key) {}

componentDidMount() {} //生命周期-初始

componentWillUnmount() {} //生命周期-卸载
/* ===== 渲染 WeaTab ===== */

render() {
const { selectedKey } = this.state
let datas = [...this.props.datas]
const newProps = {
...this.props,
datas,
_noOverwrite: true,
}
return (
<>
<WeaTab {...newProps} /> 
</>
)
}
}
// 发布组件
ecodeSDK.setCom('${appId}', 'NewWeaTabCom', NewWeaTabCom)

请求接口

WeaTools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const { WeaTools } = ecCom
WeaTools.callApi(
'/api/MedicalEthicsExamination/gradeInquiry/calculateGrades',
'GET'
)
.then((response) => {
if (response) {
//console.log("接口逻辑成功")
//window.location.reload()刷新页面
} else {
//console.log("接口逻辑失败")
}
})
.catch((error) => {
//console.log("接口请求失败",error)
})

jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//

//===== GET(异步) =====
//定义
function GetCalculateUpTask(projectId, taskId, newYjjssj) {
return $.ajax({
url: `/interface/recurringtask/GetCalculateUpTask.jsp?projectId=${projectId}&taskId=${taskId}&newYjjssj=${newYjjssj}`,
type: 'GET',
})
}
//调用
GetCalculateUpTask(projectId, taskId, newYjjssj)
.done(function (res) {
console.log('GetCalculateUpTask 响应结果:', res)
})
.fail(function (err) {
console.error('请求失败:', err)
})

//===== POST =====
//定义
const paramsObj = { key: 'value', ids: [1, 2, 3] }
function ListeningModelSave(paramsObj) {
return $.ajax({
url: '/interface/JZW/ListeningModelSave.jsp',
type: 'POST',
data: paramsObj,
traditional: true,
})
}
//调用
ListeningModelSave(paramsObj)
.done(function (res) {
console.log('ListeningModelSave 响应结果:', res)
})
.fail(function (xhr, status, err) {
console.error('请求失败:', err)
})

接口拦截

拦截请求

1
2
3
4
5
6
7
8
9
10
11
12
13
ecodeSDK.rewriteApiParamsQueueSet({
fn: (url, method, params) => {
if (url.indexOf('/api/cube/mode/mode/saveBatchImportInfo') !== -1) {
return {
url: url,
method: method,
params: { ...params, fname: wenjianname },
}
}
return { url, method, params }
},
desc: '修改流程分页接口的默认查询条件', // 描述用途
})

拦截响应

1
2
3
4
5
6
7
8
9
10
11
12
//拦截接口响应
ecodeSDK.rewriteApiDataQueueSet({
fn: function (url, params, data) {
if (url.indexOf('/api/hrm/kq/group/getForm') > -1) {
const newData = JSON.parse(JSON.stringify(data))
console.log('拦截到接口:', newData)
return newData
}
return data
},
desc: '拦截接口响应',
})

提醒

交互

1
2
3
4
5
6
7
window.antd.Modal.info({
title: '提示',
content: '您本次测试成绩为:' + df + '分',
onOk() {
callback()
},
})

气泡

1
2
3
4
5
6
7
8
9
10
11
12
//流程表单,0提示,1错误,2警告,3成功
WfForm.showMessage('这里是自定义提示内容')
//建模表单,0提示,1错误,2警告,3成功
ModeForm.showMessage('这里是自定义提示内容')
//全局
const { message } = antd
message.success(content, duration)
message.error(content, duration)
message.info(content, duration)
message.warning(content, duration)
message.warn(content, duration)
message.loading(content, duration)

获取设备信息

1
2
3
4
5
6
7
8
9
10
11
// 判断PC端or移动端
function isMobile() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
navigator.userAgent
)
}
if (isMobile()) {
console.log('当前是移动端')
} else {
console.log('当前是PC端')
}

获取用户信息

ecode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const userInfo = JSON.parse(localStorage.getItem('theme-account'))
/**
1. **`subcompanyid`: "0"**
→ 所属子公司的 ID,"0" 可能表示“无”或“总公司/默认公司”。
2. **`jobs`: ""**
→ 用户职位/岗位,当前为空字符串,可能未设置或无职位。
3. **`icon`: "/messager/images/icon_m_wev8.jpg"**
→ 用户头像或默认图标路径,用于前端显示。
4. **`deptid`: "0"**
→ 所属部门 ID,"0" 同样可能表示“无部门”或“顶级部门”。
5. **`subcompanyname`: ""**
→ 子公司名称,当前为空。
6. **`iscurrent`: "1"**
→ 是否为当前激活账户,"1" 通常表示“是”。
7. **`userid`: "1"**
→ 用户唯一 ID,这里是 1,通常系统管理员默认为 1。
8. **`deptname`: ""**
→ 部门名称,当前为空
9. **`userLanguage`: "7"**
→ 用户界面语言设置,"7" 可能代表某种语言编码(如中文、英文等),需查系统语言映射表。
10. **`showSearch`: false**
→ 是否显示搜索功能,false 表示隐藏。
11. **`showMore`: true**
→ 是否显示“更多”按钮或菜单,true 表示显示。
12. **`username`: "系统管理员"**
→ 用户显示名称。
13. **`fontSetting`: false**
→ 是否启用字体设置功能,false 表示未启用或隐藏。
`accountlist` 数组(多账户支持)
**/

java/jsp

1
2
User user = HrmUserVarify.getUser(request, response);
int userId = user.getUID();

检测元素是否已渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
 * 持续轮询查找元素,支持超时
 * @param {stringselector - CSS选择器
 * @param {functioncallback - 找到后执行的方法
 * @param {numberinterval - 轮询间隔(毫秒)
 * @param {numbertimeout - 超时时间(毫秒)
 */
function WatchElementReady(selector, callback, interval = 500, timeout = 10000) {
  const startTime = Date.now();
  function check() {
    const el = document.querySelector(selector);
    if (el) {
      //console.log(`元素已渲染,执行回调`);
      if (callback && typeof callback === 'function') {
        callback();
      } else {
        console.log(`未指定回调,执行默认打印`);
      }
    } else {
      const elapsed = Date.now() - startTime;
      if (elapsed >= timeout) {
        console.log(`超时(${timeout}ms),停止重试`);
        return// 停止重试
      }
      setTimeout(check, interval); // 继续重试
    }
  }
  check(); // 立即执行第一次检查
}

//调用方式
CheckWfFormLoaded(() => {
//渲染后执行
}

检测变量是否已就绪

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 轮询等待 WfForm 对象加载完成(表单SDK初始化完毕)
@param {Functioncallback - 加载成功后的回调
@param {numbermaxAttempts - 最大尝试次数(默认50次)
@param {numberinterval - 轮询间隔(默认100ms)
*/
function CheckWfFormLoaded(callback, maxAttempts = 50, interval = 100) {
let attempts = 0
const poll = setInterval(() => {
if (typeof WfForm !== 'undefined') {
clearInterval(poll)
callback() //已加载,执行回调
} else if (attempts >= maxAttempts) {
clearInterval(poll)
console.log('加载超时')
}
attempts++
}, interval)
}
//调用方式
CheckWfFormLoaded(() => {
console.log('就绪')
})

建模

ecode刷新台账表格数据

1
ModeList.reloadTable()

流程

流程表单SDK

获取主表字段值
1
2
3
4
//获取文本字段或浏览按钮主键值
var fieldvalue1 = WfForm.getFieldValue('field110')
//获取浏览按钮specialobj
var fieldvalue2 = mobx.toJS(wfform.getFieldValueObj('field110').specialobj)
修改主表字段值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//修改文本框、多行文本、选择框等字段类型
WfForm.changeFieldValue('field123', { value: '1.234' })
//修改浏览框字段的值,必须有specialobj数组结构对象
WfForm.changeFieldValue('field11_2', {
value: '2,3',
specialobj: [
{ id: '2', name: '张三' },
{ id: '3', name: '李四' },
],
})
//修改check框字段(0不勾选、1勾选)
WfForm.changeFieldValue('field123', { value: '1' })
//针对单行文本框字段类型,只读情况,支持显示值跟入库值不一致
WfForm.changeFieldValue('field123', {
value: '入库真实值',
specialobj: { showhtml: '界面显示值' },
})
监听主表字段值变化
1
2
3
4
5
6
7
8
9
10
11
//----- 主表 -----
WfForm.bindFieldChangeEvent("field27555,field27556", function(obj,id,value){
console.log("WfForm.bindFieldChangeEvent--",obj,id,value);
});
//注意:如果字段绑定事件,事件内改变本字段的值,需要setTimeout延时下
WfForm.bindFieldChangeEvent("field111", function(obj,id,value{
window.setTimeout(function(){
WfForm.changeFieldValue("field111",{value:"修改本字段值需要延时"});
}, 10);
WfForm.changeFieldValue("field222",{value:"修改非本字段不需要延时"});
});
明细表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//遍历明细表
var rowIndexStr = WfForm.getDetailAllRowIndexStr("detail_1");
var rowArr = rowIndexStr.split(",");
for (var i = 0; i < rowArr.length; i++) { var rowIndex = rowArr[i]; if (rowIndex !== "") {
var fieldMark = "field593_" + rowIndex;
var fieldValue = WfForm.getFieldValue(fieldMark);
}

//监听字段值变化
WfForm.bindDetailFieldChangeEvent('field27583', function (id, rowIndex, value) {
console.log('WfForm.bindDetailFieldChangeEvent--', id, rowIndex, value)
})

//删除明细表指定行/清空
WfForm.delDetailRow('detail_1', 'all')
WfForm.delDetailRow('detail_1', '3,6') //删除明细1行标为3,6的行

//添加明细表
WfForm.addDetailRow('detail_2', { field111: { value: '初始值' } })

//监听明细表字段值变化
WfForm.bindDetailFieldChangeEvent(
'field27583,field27584',
function (id, rowIndex, value) {
console.log('WfForm.bindDetailFieldChangeEvent--', id, rowIndex, value)
}
)
//
注册拦截
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// 保存前
WfForm.registerCheckEvent(WfForm.OPER_SAVE, function (callback) {
console.log('自定义逻辑')
callback() // 继续提交需调用callback,不调用代表阻断
})

// 保存后,页面跳转前
WfForm.registerCheckEvent(WfForm.OPER_SAVECOMPLETE, function (callback) {
console.log('自定义逻辑')
callback() // 继续提交需调用callback,不调用代表阻断
})

// 明细表行新增和删除前
WfForm.registerCheckEvent(WfForm.OPER_ADDROW + '1', function (callback) {
alert('添加明细1前执行逻辑,明细1则是OPER_ADDROW+1,依次类推')
callback() // 允许继续添加行调用callback,不调用代表阻断添加
})

WfForm.registerCheckEvent(WfForm.OPER_DELROW + '2', function (callback) {
alert('删除明细2前执行逻辑')
callback() // 允许继续删除行调用callback,不调用代表阻断删除
})

// 明细表行新增和删除后
WfForm.registerAction(WfForm.ACTION_ADDROW + '1', function (index) {
alert('添加行下标是' + index)
}) // 下标从1开始,明细1添加行触发事件,注册函数入参为新添加行下标

WfForm.registerAction(WfForm.ACTION_DELROW + '2', function (arg) {
alert('删除行下标集合是' + arg.join(','))
}) // 下标从1开始,明细2删除行触发事件

自定义按钮

自定义id/class

newButton.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#jzwAddButton {
  width60px;
  height30px;
  background-colorrgb(45183245!important;
  border-radius2px !important;
  color: white !important;
  display: inline-block !important;
  font-size15px !important;
  box-sizing: border-box !important;
  margin5px !important;
  text-align: center !important;
  line-height30px;
  cursor: pointer; /* 建议加上,表示可点击 */
  transition: background-color 0.2s ease; /* 可选:增加过渡效果更流畅 */
  user-select: none;/*禁止内部元素文本选中*/
}
#jzwAddButton span {
  color: white !important;
}
#jzwAddButton:hover {
  background-colorrgb(65193255!important/* 稍浅的蓝色 */
}

newButton.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
if (/#\/main\/workflow\/req\?([^&]*&)*workflowid=63(&|$)/.test(location.href)) {
console.log('【copy-detailed】 触发')

//========== 方法定义 ==========
function WaitForElement(selector, callback, timeout = 10000) {
const startTime = Date.now()
const interval = setInterval(() => {
const element = document.querySelector(selector)
if (element) {
clearInterval(interval)
callback(element)
} else if (Date.now() - startTime > timeout) {
clearInterval(interval)
console.warn(`[WaitForElement] 超时未找到元素: ${selector}`)
}
}, 200) // 每 200ms 检查一次
}
function CustomizeButton(btn) {
// 防止重复绑定(可选)
const hasCustomHandler = btn.dataset.customHandler
if (hasCustomHandler) return
btn.dataset.customHandler = 'true' // 标记已绑定
// 绑定在父级稳定元素上(比如 document)
document.addEventListener('click', function (e) {
if (e.target.closest && e.target.closest('#jzwAddButton')) {
e.preventDefault()
ButtonClick()
}
})
}
function ButtonClick() {
console.log('自定义按钮点击逻辑')
}

// ========== 逻辑执行 ==========
WaitForElement('#jzwAddButton', CustomizeButton)
}

后端

自定义API

泛微标准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.api.MedicalEthicsExamination;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import weaver.general.BaseBean;
import weaver.conn.RecordSet;

@Path("/MedicalEthicsExamination/Organization")
public class GetLeader {
@GET
@Path("/getData")
public String updateScorePublicAction(@Context HttpServletRequest request, @Context HttpServletResponse response){
//打印日志
BaseBean log =new BaseBean();
log.writeLog("自定义XXX接口开始执行");

//获取前端传参:userId
String userIdParam = request.getParameter("userId");

//。。。代码逻辑。。。

//构建返回结构
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("ascription", ascription);
dataMap.put("kpdyId", kpdyId);

JSONObject responseData = new JSONObject();
responseData.put("code", 200);
responseData.put("msg", "success");
responseData.put("data", dataMap);

return responseData.toJSONString();
}}

JSP接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<%@ page import="java.util.*" %>
<%@ page import="com.alibaba.fastjson.JSONObject" %>
<%@ page import="com.weaver.general.BaseBean" %>
<%@ page import="weaver.conn.RecordSet" %>
<%@ page contentType="application/json;charset=UTF-8" language="java" %>
<%
    //初始化打印日志对象
    BaseBean log = new BaseBean();
    log.writeLog("删除HIS排班jsp逻辑开始执行");

    //获取前端传参
    String[] ids = request.getParameterValues("ids");
    String kqzID = request.getParameter("kqzid");

    //sql操作
    RecordSet rs = new RecordSet();
    String sql = "SELECT * FROM tableName";
    rs.executeQuery(sql);
    while (rs.next()) {
    String bcid = rs.getString("bcid")
    }

    //初始化返回结构

    JSONObject res = new JSONObject();
    res.put("data", "666");
    out.print(res.toString());
%>

对外提供免认证

1
2
3
4
5
在配置文件添加接口url白名单:
Weaver/ecology/WEB-INF/prop/weaver_session_filter.properties
//unchecksessionurl后,用分号隔开
unchecksessionurl=/api/Pushpersonneldeptpinformation/PushData;/api/portal/themeCenter/getMyTheme;/api/hrm/login/getQrsLabels;

数据库操作

查询

1
2
3
4
5
6
7
8
9
String getLeaderSQL="select id from uf_hfkpdy where kpxzzc = ?";
RecordSet getLeaderRS =new RecordSet();
getLeaderRS.executeQuery(getLeaderSQL,userIdParam);
if(getLeaderRS.next()){
log.writeLog("getLeaderRS查询成功");
kpdyId=getLeaderRS.getString("id");
}else{
log.writeLog("getLeaderRS查询失败");
}

更新&插入&删除

1
2
3
4
5
6
7
8
String updateSQL = "UPDATE cus_fielddata SET field21=?";
RecordSet updateRS = new RecordSet();
boolean updateSuccess = updateRS.executeUpdate(updateSQL, newScore);
if(updateSuccess && updateRS.getUpdateCount() > 0) {
log.writeLog("更新成功,影响行数:" + updateRS.getUpdateCount());
} else {
log.writeLog("更新失败);
}

权限重构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
String uuid = UUID.randomUUID().toString();
Date now = new Date();
String createdate = new java.text.SimpleDateFormat("yyyy-MM-dd").format(now);
String createtime = new java.text.SimpleDateFormat("HH:mm:ss").format(now);
int creatorId = 1;
int creatorType = 0;
int formmodeId = 538;//建模模块id

//执行插入语句
RecordSet rs = new RecordSet();
String insertSql = "INSERT INTO uf_ryjkfhz(ry, jkfleib, fs, nd, modeuuid, formmodeid, modedatacreater, modedatacreatertype, modedatacreatedate, modedatacreatetime) " +
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
boolean success = rs.executeUpdate(insertSql,
userId,
workflowId,
score.toString(),
year,
uuid,
formmodeId,
creatorId,
creatorType,
createdate,
createtime
);
// 通过 modeuuid 查询刚插入的主键 ID
Integer newDataId = null;
if (rs.getUpdateCount() > 0) {
String queryIdSql = "SELECT id FROM uf_ryjkfhz WHERE modeuuid = ?";
if (rs.executeQuery(queryIdSql, uuid) && rs.next()) {
newDataId = rs.getInt("id");
} else {
log.writeLog(">>> 插入成功但未能通过 modeuuid 查询到主键 ID");
}
}
//权限重构
if (newDataId != null && newDataId > 0) {
ModeRightInfo modeRightInfo = new ModeRightInfo();
modeRightInfo.editModeDataShare(creatorId, formmodeId, newDataId);
log.writeLog("【xxx】权限重构成功");
} else if (success) {
log.writeLog("【xxx】插入成功,但没有获取 newDataId,跳过权限设置");
} else {
log.writeLog("【xxx】插入失败或无影响行数");
}

批量更新&插入

1
2
3
4
5
6
7
8
9
List valueList = new ArrayList();
valueList.add(uuid);
valueList.add(ddh);
List idList = new ArrayList();
idList.add(valueList);
//参数格式:[[uuid1,ddh1],[[uuid2,ddh2]],[[uuid3,ddh3]]]
RecordSet rs=new RecordSet();
String insertSQL ="INSERT INTO uf_IntermediateTabl (uuid, ddh) VALUES (?,?)";
rs.executeBatchSql(insertSQL,idList);

打印日志

1
2
3
4
5
//方法一
import com.weaver.general.BaseBean;

BaseBean log = new BaseBean();
log.writeLog("XXX节点附加操作开始执行");

流程

节后附加操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package weaver.workflow.MedicalEthicsExamination;

import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.Property;
import weaver.soa.workflow.request.RequestInfo;
import com.weaver.general.BaseBean;
import java.util.HashMap;
import java.util.Map;

public class MedicalEthicsExaminationUpdateScoreAi implements Action {
@Override
public String execute(RequestInfo requestInfo) {
BaseBean log = new BaseBean();
log.writeLog("XXX节点附加操作开始执行");

// 获取主表数据
Property[] props = requestInfo.getMainTableInfo().getProperty();
Map<String, String> fieldMap = new HashMap<>();
for (Property prop : props) {
fieldMap.put(prop.getName(), prop.getValue());
}
String scorePrams = fieldMap.get("df");
String userIdPrams = fieldMap.get("cpr");

//获取流程id
String workflowid = requestInfo.getWorkflowid();

//。。。代码逻辑。。。

return Action.SUCCESS;
}
}

创建流程

构建主表
1
2
3
4
5
6
7
8
9
10
11
WorkflowMainTableInfo workflowMainTableInfo = new WorkflowMainTableInfo();
WorkflowRequestTableRecord[] workflowRequestTableRecord = new WorkflowRequestTableRecord[1]; //固定值1
WorkflowRequestTableField[] WorkflowRequestTableField = new WorkflowRequestTableField[3]; //总字段数

WorkflowRequestTableField[0] = createTableField("dw", String.valueOf(currentPerson.getDw()));
WorkflowRequestTableField[1] = createTableField("nd", String.valueOf(currentPerson.getNd()));
WorkflowRequestTableField[2] = createTableField("xm", String.valueOf(currentPerson.getXm()));

workflowRequestTableRecord[0] = new WorkflowRequestTableRecord();
workflowRequestTableRecord[0].setWorkflowRequestTableFields(WorkflowRequestTableField);
workflowMainTableInfo.setRequestRecords(workflowRequestTableRecord);
构建明细表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
WorkflowDetailTableInfo[] workflowDetailTableInfo = new WorkflowDetailTableInfo[1];
WorkflowRequestTableRecord[] workflowRequestTableRecord = new WorkflowRequestTableRecord[allData.size()];

for (int i = 0; i < allData.size(); i++) {
TranscriptStructure ts = allData.get(i);
WorkflowRequestTableField[] WorkflowRequestTableField = new WorkflowRequestTableField[3]; //数据总数

WorkflowRequestTableField[0] = createTableField("xm", String.valueOf(ts.getXm()));
WorkflowRequestTableField[1] = createTableField("zggh", String.valueOf(ts.getZggh()));
WorkflowRequestTableField[2] = createTableField("kpdc", String.valueOf(ts.getKpdc()));

workflowRequestTableRecord[i] = new WorkflowRequestTableRecord();
workflowRequestTableRecord[i].setWorkflowRequestTableFields(WorkflowRequestTableField);
}

workflowDetailTableInfo[0] = new WorkflowDetailTableInfo();
workflowDetailTableInfo[0].setWorkflowRequestTableRecords(workflowRequestTableRecord);
创建
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
log.writeLog("开始为人员创建流程,人员信息:" + currentPerson.getXm());

// 创建流程信息
WorkflowRequestInfo workflowRequestInfo = new WorkflowRequestInfo();
workflowRequestInfo.setRequestName("医德考评成绩确认单");
workflowRequestInfo.setCreatorId(userId);

WorkflowBaseInfo workflowBaseInfo = new WorkflowBaseInfo();
workflowBaseInfo.setWorkflowId("25");
workflowRequestInfo.setWorkflowBaseInfo(workflowBaseInfo);

// 构建主表
WorkflowMainTableInfo workflowMainTableInfo = buildMainTableInfo(currentPerson);
workflowRequestInfo.setWorkflowMainTableInfo(workflowMainTableInfo);

// 构建明细表
WorkflowDetailTableInfo[] workflowDetailTableInfo = buildDetailTableInfo(allData);
workflowRequestInfo.setWorkflowDetailTableInfos(workflowDetailTableInfo);

// 创建流程
WorkflowServiceImpl wsi = new WorkflowServiceImpl();
String requestId = wsi.doCreateWorkflowRequest(workflowRequestInfo, userIdInt);

log.writeLog("创建流程成功,流程ID:" + requestId);

流程干预

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
try {
// 获取干预服务
WorkflowRequestOperatePAImpl service = ServiceUtil.getService(WorkflowRequestOperatePAImpl.class);
// 使用有权限的用户(这里使用admin用户)
User user = new User(1);

// 遍历所有需要干预的流程
for (Map<String, String> item : newRequestList) {
String requestId = item.get("requestId");
String xm = item.get("xm");

try {
log.writeLog("开始干预流程,requestId: " + requestId + ", 接收人: " + xm);

// 设置干预参数
ReqOperateRequestEntity requestParam = new ReqOperateRequestEntity();
requestParam.setRequestId(Integer.parseInt(requestId)); // 流程实例ID
requestParam.setSubmitNodeId(94); // 目标节点ID(独立打印节点)
requestParam.setIntervenorid(xm); // 设置接收人为当前xm

// 执行干预
PAResponseEntity result = service.doIntervenor(user, requestParam);

// 检查干预结果 - 修改为正确的枚举比较方式
if (PAResponseCode.SUCCESS.equals(result.getCode())) {
log.writeLog("干预成功,requestId: " + requestId);
successCount++;
} else {
log.writeLog("干预失败,requestId: " + requestId +
", 错误码: " + result.getCode().name() +
", 错误信息: " + result.getErrMsg());
allSuccess = false;
failCount++;
failedRequests.add(requestId);
} } catch (Exception e) {
log.writeLog("干预流程异常,requestId: " + requestId + ", 异常信息: " + e.getMessage());
allSuccess = false;
failCount++;
failedRequests.add(requestId);
} }
// 记录总体干预结果
log.writeLog("流程干预完成,成功: " + successCount + "个,失败: " + failCount + "个");
if (!failedRequests.isEmpty()) {
log.writeLog("失败的requestIds: " + failedRequests);
}
} catch (Exception e) {
log.writeLog("获取干预服务或初始化用户异常: " + e.getMessage());
allSuccess = false;
}

邮件

内部邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
E9 内部邮件发送接口
可参考 weaver.email.MailSend.java 类的 sendSysInternalMailNew 方法
* 发送内部邮件系统提醒
* @param fromid 发送人,人员id。必填。
* @param subject 邮件标题。必填。
* @param content 邮件内容。非必填。
* @param toids 接收人ids,例如1,2,3,4。 必填。
* @param ccids 抄送人ids,例如 1,2,3,4。非必填。
* @param ccids 密送人ids,例如 1,2,3,4。非必填。
* @param path 附件路径。非必填。 值为OA服务器能访问到的实体文件全路径。录入系统时文件名与实体文件名一致。
* @return
*/
mailSend.sendSysInternalMailNew(fromid, managerId, "", "", subject, content, null);

外部邮件

1

消息

企业微信

1
2
3
4
5
6
7
8
9
10
11
12
public void PushWXMessage(String userId, String content) {
List<String> userList = new ArrayList<String>();
userList.add(userId);
String tpids = "3493db33baf74b9e8200dea64698841f"; // 根据消息类型选择模板
int type = -1; // 固定为消息推送类型
try {
InterfaceUtil.sendMsg(userList, tpids, "", content, type);
log.writeLog("✅ 微信消息推送成功:用户=" + userId + ", 模板=" + tpids + ", 内容=" + content);
} catch (Exception e) {
log.writeLog("❌ 微信推送失败: " + e);
}
}

源码

打包

步骤

1
2
3
4
5
6
7
//1、安装依赖
yarn install

//2、新建spa文件夹,把项目的spa/moduleConfig.js放到下面,这是版本文件,打包的时候需要同步

//3、禁用eslint,打包流程模块
yarn build --noeslint --pubModule=workflow

其他

1
2
//禁用过滤调试打印
src4js-pctool-v1/config/webpack.config.prod 里面的 drop_console 改为false

E10

前端

获取用户信息

1

组件复写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { regOvProps } from '@weapp/utils'
regOvProps(
'weappUi',
'Table',
(props) => {
if (
props.weId ==
'xj9ztk_n9fsi1_ktapm0_93rio8_s9t7xg_ll4efn_rr53ls_vqqhsb'
) {
console.log('拦截到目标组件', props)
props.columns = props.columns.filter(
(col) => col.title !== '大小' && col.title !== '更新时间'
)
}
return props
},
0
)

组件重写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import React from 'react'
import { regOvComponent } from '@weapp/utils'
import { asyncImport } from '@weapp/ecodesdk'

const NewHelp = React.lazy(() => asyncImport('${appId}', 'NewHelp'))

regOvComponent(
'weappUi',
'Help',
(Com) => {
if (
window.location.pathname === '/sp/integration/loginSingle/freepass'
) {
return React.forwardRef((props, ref) => {
console.log('获取的help参数', props)
return (
<React.Suspense fallback={() => {}}>
     {' '}
<NewHelp
{...props}
OriginCom={Com}
ref={ref}
forwardedRef={ref}
/>
   {' '}
</React.Suspense>
)
})
}
},
1
)

请求接口

泛微标准
Axios
1
2
3
4
5
6
7
8
9
10
import axios from 'axios'
// 发起 GET 请求
axios
.get('https://api.example.com/data')
.then((response) => {
console.log('成功:', response.data)
})
.catch((error) => {
console.error('错误:', error)
})

接口拦截

响应拦截

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios.interceptors.response.use(
(response) => {
if (response.config.url === '/api/doc/document/queryInfo') {
const createUserId =
response.data?.data?.document?.author?.employeeId
if (createUserId && createUserId !== userId) {
console.log('PC:非创建人,删除 share/log 元素')
waitForElementsAndDelete(['share', 'log'])
}
}
return response
},
(error) => Promise.reject(error)
)

请求拦截

1
2
3
4
5
6
7
8
axios.interceptors.request.use((request) => {
if (request.url === '/api/ebuilder/coms/list/getData') {
const params = new URLSearchParams(request.data)
params.set('pageSize', '10000')
request.data = params.toString()
}
return request
})

调用数据加工

1
2
3
4
5
6
7
8
9
10
11
12
13
//定义
function GetTotalCount() {
return new Promise((resolve) => {
const ebSdk = window.ebuilderSDK
console.log('window.ebuilderSDK', ebSdk) // SQL 数据源 ID: 1040519435904892928
ebSdk.SQL('1040519435904892928', function (result) {
resolve(result?.[0] || { total_count: 0 })
})
})
}
//使用
const box = await GetTotalCount()
console.log('box', box)

流程

表单SDK

1
2
3
4
5
6
7
8
9
// 获取字段值
const idTypeFieldId = formSdk.convertFieldNameToId('zjlx')
const idTypeValue = formSdk.getFieldValue(idTypeFieldId)

// 监听字段值变化
const idNumberFieldId = formSdk.convertFieldNameToId('zjhm')
formSdk.bindFieldChangeEvent(idNumberFieldId, (data) => {
console.log('【证件号码】的内容变化了:', data)
})

提醒

1
2
const wffpSdk = window.weappWorkflow.getFlowPageSDK()
wffpSdk.showMessage('身份证号码格式错误,请输入15位或18位有效号码', 1, 3)

自定义组件

1
2
3
4
5
6
7
8
//view.js
import React from 'react'
import Index from './index'
const View = (props) => {
const { config } = props
return <Index />
}
export default View
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//Design.js
import React from 'react'
import { getLabel } from '@weapp/utils'
import Index from './index'

const Design = (props) => {
const { config } = props
return <Index />
}

// 自定义组件props不要使用type字段,type字段会被赋值当前组件的类型

// 设置默认值设计器才会有默认配置

Design.defaultProps = {
config: {
content: getLabel('187481', '示例组件'),
},
}

// 定制化配置流式布局的默认属性
Design.flow = {
defaultProps: {
config: {
content: getLabel('187481', '示例组件'),
},
},
}

// 看代码逻辑grid布局的组件必须设置属性defaultOpts.layoutSizes
Design.defaultOpts = {
operationBtns: true,
mask: false,
layoutSizes: {
gl: {
w: 4,
h: 15,
},
mgl: { adaptive: true, h: 150 },
},
}
export default Design
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//index.js
import React, { PureComponent } from 'react';
import { withRouter } from 'react-router-dom';
import { observer } from 'mobx-react';
import { dayjs, request, classnames } from '@weapp/utils';
import './index.css';

function getTotalCount() {
  return new Promise((resolve) => {
    const ebSdk = window.ebuilderSDK;
    // SQL 数据源 ID: 1040519435904892928,预期返回形如 [{ total_count: number }]
    ebSdk.SQL("1040519435904892928", function (result) {
      resolve(result?.[0] || { total_count: 0 });
    });
  });
}
// 调用接口获取合同即将到期的员工数量(按不同到期天数分类)
function getEx() {
  return request({
    url: '/api/hr/contract/calc/expire',
    method: 'post'
  });
}

@observer
export class JzwLunBo extends PureComponent<any, any> {
  constructor(props: any) {
    super(props);
    this.state = {
    };
  }
  // 组件挂载后发起数据请求
  componentDidMount() {}
  // 渲染主视图
  render() {
    return (
      <div>6666666666666</div>
    );
  }
}
// 使用 withRouter 注入路由相关 props(如 history, location 等)
export default withRouter(JzwLunBo);

后端

获取用户信息

1
2
final SimpleEmployee currentUser = UserContext.getCurrentUser();
userId = currentUser.getUid();

自定义接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//加/papi和publicPermission=true代表对外开放,不需要认证

@Slf4j
@RestController
@RequestMapping("/papi/secondev/signatureservlet")
@WeaPermission(publicPermission = true)
public class GetSignatureServlet {
@Autowired
private DataSetService dataSetService;
@GetMapping("/getimage")
public void GetSignatureServletMain(HttpServletRequest request, HttpServletResponse response) throws IOException {
log.error("【GetSignatureServlet】开始获取个人签章逻辑");
String loginName = Util.null2String(request.getParameter("loginname"));
log.error("【GetSignatureServlet】获取到的 loginname 参数: '{}'", loginName);
}
}

请求接口

GET

1
2
3
4
5
6
7
String url = "http://124.129.136.6:20600/papi/openapi/api/file/v2/common/download/"+fileId;

HttpResponse response = HttpRequest.get(url)
.form("access_token", accessToken)
.form("userid", userId).execute();

log.error("【GetSignatureServlet】获取响应体: {}", response.body());

POST

1
2
3
4
5
6
7
8
9
10
11
JSONObject requestBody = JSONUtil.createObj()
.set("app_key", "e71073dc1872ecffc70d5d02a4faab8a")
.set("app_secret", "4a73729149560b48ce6800cc789369a6")
.set("grant_type", "authorization_code")
.set("code", code);
String accessTokenURL = "http://124.129.136.6:20600/papi/openapi/oauth2/access_token";
HttpResponse response = HttpRequest.post(accessTokenURL)
.body(requestBody.toString())
.header("Content-Type", "application/json")
.execute();
log.error("【GetSignatureServlet】获取到的 accessToken 完整响应体: {}", response.body());

使用开放平台接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public String GetAccessToken() {
log.error("【GetSignatureServlet】执行 获取 code 方法");
String url = "http://124.129.136.6:20600/papi/openapi/oauth2/authorize";
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("corpid", "fabf265f7b0dd7d298ad5f12a0638f40");
paramMap.put("response_type", "code");
paramMap.put("state", "xxx");
String responseBody = HttpUtil.get(url, paramMap);
JSONObject jsonResponse = JSONUtil.parseObj(responseBody);
String code = jsonResponse.getStr("code");
log.error("【GetSignatureServlet】获取到的 code: {}", code);

JSONObject requestBody = JSONUtil.createObj()
.set("app_key", "e71073dc1872ecffc70d5d02a4faab8a")
.set("app_secret", "4a73729149560b48ce6800cc789369a6")
.set("grant_type", "authorization_code")
.set("code", code);
String accessTokenURL = "http://124.129.136.6:20600/papi/openapi/oauth2/access_token";
HttpResponse response = HttpRequest.post(accessTokenURL)
.body(requestBody.toString())
.header("Content-Type", "application/json")
.execute();
// log.error("【GetSignatureServlet】获取到的 accessToken 完整响应体: {}", response.body());
JSONObject accessTokenJsonResponse = JSONUtil.parseObj(response.body());
String accessToken = accessTokenJsonResponse.getStr("accessToken");
log.error("【GetSignatureServlet】获取到的 accessToken: {}", accessToken);
return accessToken;
}

数据库操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Autowired
private DataSetService dataSetService;
//查询
public Boolean SelectInConfigurationTable(FileObj fileObj){
log.error("开始查询附件是否在建模配置表中");
//根据文档id查询所在文件夹id
String sql = "SELECT folder_id FROM document_folder_link";
ExecuteSqlEntity executeSqlEntity = new ExecuteSqlEntity();
executeSqlEntity.setSql(cn.hutool.core.codec.Base64.encode(sql));
executeSqlEntity.setGroupId("weaver-doc-service");
executeSqlEntity.setSourceType(SourceType.LOGIC);

Map<String, Object> datas ==dataSetService.executeSql(executeSqlEntity);
List<LinkedHashMap<String, Object>> recordsList = (List<LinkedHashMap<String, Object>>) datas.get("records");
if (recordsList != null && !recordsList.isEmpty()) {
log.error("数据库查询的结果集:{}", recordsList);
}
}

打印日志

引入并使用Slf4j注解,打印参数使用占位符{}

1
2
3
4
5
6
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FileWatermarkHookDemo {
log.error("打印的日志,参数:{}",params);
}

默认输出级别是error,其他的不打印

判断数据库字段类型

1
SELECT data_type, data_length FROM all_tab_columns WHERE table_name = 'tableName' AND column_name = 'columnName';

获取GroupId

1
http://产品ip:端口/api/datasource/ds/group?sourceType=LOGIC
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
{
"code": 200,
"msg": "接口返回成功",
"data": [
{
"name": "业务表单",
"serviceMark": "form",
"id": "weaver-formreport-service"
},
{
"name": "流程",
"serviceMark": "workflow",
"id": "weaver-workflow-report-serviceworkflowreport"
},
{
"name": "任务",
"serviceMark": "task",
"id": "weaver-project-servicetask"
},
{
"name": "日志",
"serviceMark": "elog",
"id": "weaver-elog-service"
},
{
"name": "会议",
"serviceMark": "meeting",
"id": "weaver-meetings-service"
},
{
"name": "日程",
"serviceMark": "blog",
"id": "weaver-blog-service"
},
{
"name": "OKR",
"serviceMark": "goal",
"id": "weaver-hrm-goal-service"
},
{
"name": "流程列表",
"serviceMark": "list",
"id": "weaver-workflow-list-service"
},
{
"name": "考勤",
"serviceMark": "attend",
"id": "weaver-attend-service"
},
{
"name": "组织画像",
"serviceMark": "portrait",
"id": "weaver-portrait-service"
},
{
"name": "工作流",
"serviceMark": "workflow",
"id": "weaver-workflow-report-serviceworkflow_report"
},
{
"name": "绩效",
"serviceMark": "kpi",
"id": "weaver-wr-performance-service"
},
{
"name": "基础定时模块",
"serviceMark": "scheduler",
"id": "weaver-basic-schedule-service"
},
{
"name": "知识画像",
"serviceMark": "document",
"id": "weaver-doc-service"
},
{
"name": "HRM",
"serviceMark": "hrm",
"id": "weaver-hrm-service"
},
{
"name": "e-builder报表",
"serviceMark": "esb",
"id": "weaver-esb-report-service"
},
{
"name": "e-builder应用",
"serviceMark": "builder",
"id": "weaver-ebuilder-app-service"
},
{
"name": "e-builder表单",
"serviceMark": "builder",
"id": "weaver-ebuilder-form-service"
},
{
"name": "客户管理",
"serviceMark": "customer",
"id": "weaver-customer-service"
},
{
"name": "日程",
"serviceMark": "calendar",
"id": "weaver-calendar-service"
},
{
"name": "文档",
"serviceMark": "document",
"id": "weaver-doc-servicedocument"
},
{
"name": "文件",
"serviceMark": "file",
"id": "weaver-file-service"
},
{
"name": "数据源",
"serviceMark": "datasource",
"id": "weaver-datasource-service"
},
{
"name": "电子签章",
"serviceMark": "esigncontract",
"id": "weaver-signcenter-service"
},
{
"name": "行为流",
"serviceMark": "ilsh",
"id": "weaver-ilshn-service"
},
{
"name": "动作流",
"serviceMark": "esb",
"id": "weaver-esb-settings-services"
},
{
"name": "表单加密",
"serviceMark": "datasecurity",
"id": "weaver-datasecurity"
},
{
"name": "薪酬",
"serviceMark": "salary-report",
"id": "weaver-salary-report"
},
{
"name": "人事",
"serviceMark": "hr",
"id": "weaver-hr-service"
},
{
"name": "发票云",
"serviceMark": "inc",
"id": "weaver-inc-biz-service"
},
{
"name": "租户",
"serviceMark": "tenant",
"id": "weaver-tenant-service"
},
{
"name": "绩效核算",
"serviceMark": "builder",
"id": "weaver-builder-contract-servicecustom"
},
{
"name": "待办事项",
"serviceMark": "todo",
"id": "weaver-todo-service"
},
{
"name": "签名",
"serviceMark": "signature",
"id": "weaver-signature-service"
},
{
"name": "邮件",
"serviceMark": "email",
"id": "weaver-mail-base-service"
},
{
"name": "薪酬",
"serviceMark": "hrm-salary",
"id": "weaver-hrm-salary"
},
{
"name": "系统安全",
"serviceMark": "security",
"id": "weaver-security-framework-service"
},
{
"name": "档案管理",
"serviceMark": "archive",
"id": "weaver-archive-core-service"
},
{
"name": "招聘管理",
"serviceMark": "recruit",
"id": "weaver-recruit-service"
},
{
"name": "基础在线服务",
"serviceMark": "weaver-basic-online-web-service",
"id": "weaver-basic-online-web-service"
},
{
"name": "微搜",
"serviceMark": "search",
"id": "weaver-search-service"
},
{
"name": "统一审批中心",
"serviceMark": "intunifytodo",
"id": "weaver-intunifytodo-server-config-service"
},
{
"name": "统一待办服务",
"serviceMark": "intunifytodo",
"id": "weaver-intunifytodo-client-config-service"
},
{
"name": "公共数据源",
"serviceMark": "common",
"id": "weaver-component-web-service"
},
{
"name": "ESB连接",
"serviceMark": "esb",
"id": "weaver-esb-setting-serviceesbConnect"
},
{
"name": "AI连接",
"serviceMark": "ai",
"id": "weaver-ai-application-service"
},
{
"name": "外部流程",
"serviceMark": "workflow",
"id": "weaver-workflow-core-serviceExternalCoreOutflow"
},
{
"name": "绩效考核",
"serviceMark": "builder",
"id": "weaver-wr-performance-eb-service"
},
{
"name": "登录服务",
"serviceMark": "passport",
"id": "weaver-passport-service"
},
{
"name": "工作流表单",
"serviceMark": "workflow",
"id": "weaver-workflow-report-serviceworkflowReport"
},
{
"name": "统一认证中心",
"id": "weaver-intunifyauth-server-base-service"
},
{
"name": "sap数据源",
"serviceMark": "int sap",
"id": "weaver-int sap-web-service"
}
],
"fail": false
}