iBizModel 系统数据同步代理(PSSYSDATASYNCAGENT)与实体数据同步(PSDEDATASYNC)应用示例(1)

一、两个数据同步模型全景分析

案例1:InStorageSync(OUT方向 --- 定时输出同步)

业务场景 :供应链入库实体(Supply_Chain_Mgmt.IN_STORAGE) 每天定时将入库数据按仓库位置分组导出CSV文件,通过FTP回写到外部系统。

关联模型关系图

#mermaid-svg-ZfXUZSWNdW07naM1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZfXUZSWNdW07naM1 .error-icon{fill:#552222;}#mermaid-svg-ZfXUZSWNdW07naM1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZfXUZSWNdW07naM1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZfXUZSWNdW07naM1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 .marker.cross{stroke:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZfXUZSWNdW07naM1 p{margin:0;}#mermaid-svg-ZfXUZSWNdW07naM1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster-label text{fill:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster-label span{color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster-label span p{background-color:transparent;}#mermaid-svg-ZfXUZSWNdW07naM1 .label text,#mermaid-svg-ZfXUZSWNdW07naM1 span{fill:#333;color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .node rect,#mermaid-svg-ZfXUZSWNdW07naM1 .node circle,#mermaid-svg-ZfXUZSWNdW07naM1 .node ellipse,#mermaid-svg-ZfXUZSWNdW07naM1 .node polygon,#mermaid-svg-ZfXUZSWNdW07naM1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .rough-node .label text,#mermaid-svg-ZfXUZSWNdW07naM1 .node .label text,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape .label,#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZfXUZSWNdW07naM1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .rough-node .label,#mermaid-svg-ZfXUZSWNdW07naM1 .node .label,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape .label,#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape .label{text-align:center;}#mermaid-svg-ZfXUZSWNdW07naM1 .node.clickable{cursor:pointer;}#mermaid-svg-ZfXUZSWNdW07naM1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 .arrowheadPath{fill:#333333;}#mermaid-svg-ZfXUZSWNdW07naM1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZfXUZSWNdW07naM1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZfXUZSWNdW07naM1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZfXUZSWNdW07naM1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZfXUZSWNdW07naM1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZfXUZSWNdW07naM1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster text{fill:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 .cluster span{color:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZfXUZSWNdW07naM1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZfXUZSWNdW07naM1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape p,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZfXUZSWNdW07naM1 .icon-shape .label rect,#mermaid-svg-ZfXUZSWNdW07naM1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZfXUZSWNdW07naM1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZfXUZSWNdW07naM1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZfXUZSWNdW07naM1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 处理逻辑 PSDELOGIC
后端插件 PSSYSSFPLUGIN
系统数据同步代理 PSSYSDATASYNCAGENT
导出表格 PSDEGRID
数据导出 PSDEDATAEXP
输出数据集 PSDEDATASET
实体数据同步 PSDEDATASYNC
所属实体 PSDATAENTITY
psdeid
psdeid
psdeid
psdeid
outpsdedatasetid
outpssysdatasyncagentid
psdedataexpid
pssyssfpluginid
psdegridid
psdelogicid
filtermodel.groupFields=stor_location
Supply_Chain_Mgmt.IN_STORAGE

入库实体
InStorageSync

入库数据输出同步

syncdir=OUT

outmode=2(定时)

eventtype=7(新建+更新+删除)

timerpolicy=定时CRON
SyncInStorageToSAP

入库数据导出数据集

predefinedtype=DELOGIC

基于处理逻辑的数据集
InStorageSync

入库数据导出

contenttype=CSV

filenameformat=带时间戳的CSV文件
InStorageExportSync

导出列定义
FTPOutputAgent

FTP回写代理

agenttype=FILE

syncdir=OUT

servicepath=外部FTP路径
GroupDEDataSyncOutRuntime

分组数据同步输出运行时
SyncInStorageToSAPLogic

提供数据集查询逻辑

DSL代码解析
groovy 复制代码
// PSDEDATASYNC - 实体数据同步
psdedatasync(
    name: "入库数据输出同步", 
    codename: "InStorageSync", 
    outmode: 2,                    // 定时输出
    eventtype: 7,                  // 新建1+更新2+删除4=7(全事件)
    filtermodel: "{\"groupFields\":\"stor_location\",\"afterDEAction\":\"SyncInStorageToSAPExport\"}",
    memo: "[业务编码]", 
    outpsdedatasetid: "Supply_Chain_Mgmt.IN_STORAGE.SyncInStorageToSAP",  // 输出数据集
    outpssysdatasyncagentid: "System_Mgmt.FTPOutputAgent",                // 输出代理
    psdedataexpid: "Supply_Chain_Mgmt.IN_STORAGE.InStorageSync",          // 数据导出
    psdeid: "Supply_Chain_Mgmt.IN_STORAGE",                                // 所属实体
    pssyssfpluginid: "GroupDEDataSyncOutRuntime",                          // 后端插件(分组输出)
    syncdir: "OUT",                                                        // 输出方向
    timerpolicy: "定时CRON表达式"                                          // 每天定时执行
)
// PSSYSDATASYNCAGENT - 系统数据同步代理(FTP输出)
pssysdatasyncagent(
    name: "FTP回写代理", 
    codename: "FTPOutputAgent", 
    agenttype: "FILE",              // 文件类型代理
    authclientid: "认证客户端ID", 
    authclientsecret: "认证密钥", 
    authmode: "PASSWORD", 
    psmoduleid: "System_Mgmt", 
    servicepath: "外部FTP服务路径",   // FTP目标地址
    syncdir: "OUT"                  // 输出方向
)
// PSDEDATAEXP - 数据导出(CSV格式)
psdedataexp(
    name: "入库数据导出", 
    codename: "InStorageSync", 
    filenameformat: "前缀_{#date_fmt.format('yyyyMMddHHmmss')}.csv", 
    contenttype: "CSV", 
    defaultflag: 0, 
    psdegridid: "Supply_Chain_Mgmt.IN_STORAGE.InStorageExportSync",  // 导出表格
    psdeid: "Supply_Chain_Mgmt.IN_STORAGE"
)
// PSDEDATASET - 输出数据集(基于处理逻辑)
psdedataset(
    name: "SyncInStorageToSAP", 
    codename: "SyncInStorageToSAP", 
    logicname: "入库数据导出数据集", 
    psdeid: "Supply_Chain_Mgmt.IN_STORAGE", 
    psdelogicid: "Supply_Chain_Mgmt.IN_STORAGE.SyncInStorageToSAPLogic",  // 关联处理逻辑
    predefinedtype: "DELOGIC"                                              // 基于处理逻辑
)

案例2:InboundSync(IN方向 --- 定时输入同步)

业务场景 :对账实体(Statement_Mgmt.STATEMENTENTITY) 每天定时从外部系统共享文件夹读取指定模式文件,通过TSV格式导入解析,调用批量导入行为写入数据库。

关联模型关系图

#mermaid-svg-skhIumX3DxYSKMam{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-skhIumX3DxYSKMam .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-skhIumX3DxYSKMam .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-skhIumX3DxYSKMam .error-icon{fill:#552222;}#mermaid-svg-skhIumX3DxYSKMam .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-skhIumX3DxYSKMam .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-skhIumX3DxYSKMam .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-skhIumX3DxYSKMam .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-skhIumX3DxYSKMam .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-skhIumX3DxYSKMam .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-skhIumX3DxYSKMam .marker{fill:#333333;stroke:#333333;}#mermaid-svg-skhIumX3DxYSKMam .marker.cross{stroke:#333333;}#mermaid-svg-skhIumX3DxYSKMam svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-skhIumX3DxYSKMam p{margin:0;}#mermaid-svg-skhIumX3DxYSKMam .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster-label text{fill:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster-label span{color:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster-label span p{background-color:transparent;}#mermaid-svg-skhIumX3DxYSKMam .label text,#mermaid-svg-skhIumX3DxYSKMam span{fill:#333;color:#333;}#mermaid-svg-skhIumX3DxYSKMam .node rect,#mermaid-svg-skhIumX3DxYSKMam .node circle,#mermaid-svg-skhIumX3DxYSKMam .node ellipse,#mermaid-svg-skhIumX3DxYSKMam .node polygon,#mermaid-svg-skhIumX3DxYSKMam .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .rough-node .label text,#mermaid-svg-skhIumX3DxYSKMam .node .label text,#mermaid-svg-skhIumX3DxYSKMam .image-shape .label,#mermaid-svg-skhIumX3DxYSKMam .icon-shape .label{text-anchor:middle;}#mermaid-svg-skhIumX3DxYSKMam .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .rough-node .label,#mermaid-svg-skhIumX3DxYSKMam .node .label,#mermaid-svg-skhIumX3DxYSKMam .image-shape .label,#mermaid-svg-skhIumX3DxYSKMam .icon-shape .label{text-align:center;}#mermaid-svg-skhIumX3DxYSKMam .node.clickable{cursor:pointer;}#mermaid-svg-skhIumX3DxYSKMam .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-skhIumX3DxYSKMam .arrowheadPath{fill:#333333;}#mermaid-svg-skhIumX3DxYSKMam .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-skhIumX3DxYSKMam .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-skhIumX3DxYSKMam .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-skhIumX3DxYSKMam .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-skhIumX3DxYSKMam .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-skhIumX3DxYSKMam .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-skhIumX3DxYSKMam .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-skhIumX3DxYSKMam .cluster text{fill:#333;}#mermaid-svg-skhIumX3DxYSKMam .cluster span{color:#333;}#mermaid-svg-skhIumX3DxYSKMam div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-skhIumX3DxYSKMam .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-skhIumX3DxYSKMam rect.text{fill:none;stroke-width:0;}#mermaid-svg-skhIumX3DxYSKMam .icon-shape,#mermaid-svg-skhIumX3DxYSKMam .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-skhIumX3DxYSKMam .icon-shape p,#mermaid-svg-skhIumX3DxYSKMam .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-skhIumX3DxYSKMam .icon-shape .label rect,#mermaid-svg-skhIumX3DxYSKMam .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-skhIumX3DxYSKMam .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-skhIumX3DxYSKMam .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-skhIumX3DxYSKMam :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 后端插件 PSSYSSFPLUGIN
实体行为 PSDEACTION
系统数据同步代理 PSSYSDATASYNCAGENT
数据导入 PSDEDATAIMP
实体数据同步 PSDEDATASYNC
所属实体 PSDATAENTITY
psdeid
psdeid
psdeid
inpssysdatasyncagentid
psdedataimpid
createpsdeactionid
pssyssfpluginid
filtermodel.file=文件匹配模式
包含
导入项映射(多项)
vendor_do_no -> VENDOR_DO_NO
customer_po_no -> CUSTOMER_PO_NO
product_code -> PRODUCT_CODE
entry_quantity -> ENTRY_QUANTITY
entry_amount -> ENTRY_AMOUNT
... 共多个字段映射
Statement_Mgmt.STATEMENTENTITY

对账实体
InboundSync

入库数据同步

syncdir=IN

eventtype=7

timerpolicy=定时CRON

filtermodel={file:文件匹配模式}
Inbound

入库数据同步

contenttype=TSV

stopwhenerror=0

enablecustomized=1
FileInputAgent

文件输入代理

agenttype=FILE

syncdir=IN

servicepath=外部共享路径
StatementBatchImport

批量导入行为
CustomDEDataImportRuntime

自定义数据导入运行时

DSL代码解析
groovy 复制代码
// PSDEDATASYNC - 实体数据同步(输入)
psdedatasync(
    name: "入库数据同步", 
    codename: "InboundSync", 
    eventtype: 7,                                    // 全事件
    filtermodel: "{\"file\":\"文件匹配模式\"}",      // 文件过滤模式
    inpssysdatasyncagentid: "System_Mgmt.FileInputAgent",  // 输入代理
    memo: "[业务编码]实现从文件提取后的临时表数据导入...", 
    psdedataimpid: "Statement_Mgmt.STATEMENTENTITY.Inbound",  // 数据导入
    psdeid: "Statement_Mgmt.STATEMENTENTITY", 
    syncdir: "IN",                                   // 输入方向
    timerpolicy: "定时CRON表达式"                     // 每天定时执行
)
// PSSYSDATASYNCAGENT - 系统数据同步代理(文件输入)
pssysdatasyncagent(
    name: "文件输入代理", 
    codename: "FileInputAgent", 
    agenttype: "FILE",                               // 文件类型代理
    psmoduleid: "System_Mgmt", 
    servicepath: "外部共享文件路径", 
    syncdir: "IN"                                    // 输入方向
)
// PSDEDATAIMP - 数据导入(TSV格式,含多个字段映射)
psdedataimp(
    name: "入库数据同步", 
    codename: "Inbound", 
    contenttype: "TSV",                              // TSV格式
    createpsdeactionid: "Statement_Mgmt.STATEMENTENTITY.StatementBatchImport",  // 批量导入行为
    defaultflag: 0, 
    enablecustomized: 1,                             // 支持定制
    psdeid: "Statement_Mgmt.STATEMENTENTITY", 
    pssyssfpluginid: "CustomDEDataImportRuntime",    // 自定义导入运行时
    stopwhenerror: 0                                 // 出错不中止
){
    // 多个导入字段映射(示例部分)
    psdedataimpitem(id: "vendor_do_no", name: "vendor_do_no", caption: "Vendor DO No.", keyflag: 0, ordervalue: 1, psdefid: "Statement_Mgmt.STATEMENTENTITY.VENDOR_DO_NO")
    psdedataimpitem(id: "product_code", name: "product_code", caption: "Material", keyflag: 0, ordervalue: 8, psdefid: "Statement_Mgmt.STATEMENTENTITY.PRODUCT_CODE")
    psdedataimpitem(id: "entry_quantity", name: "entry_quantity", caption: "Quantity", keyflag: 0, ordervalue: 10, psdefid: "Statement_Mgmt.STATEMENTENTITY.ENTRY_QUANTITY")
    psdedataimpitem(id: "purchasing_document", name: "purchasing_document", caption: "Purchasing Doc.", keyflag: 1, ordervalue: 32, psdefid: "Statement_Mgmt.STATEMENTENTITY.PURCHASING_DOCUMENT")
    // ... 其余字段省略
}

二、PSDEDATASYNC 完整关联模型体系

基于上述两个案例及模型架构定义,实体数据同步涉及的核心模型及关联关系如下:

2.1 模型关系总览

#mermaid-svg-V1PK0lnFlIIuBxEd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-V1PK0lnFlIIuBxEd .error-icon{fill:#552222;}#mermaid-svg-V1PK0lnFlIIuBxEd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V1PK0lnFlIIuBxEd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V1PK0lnFlIIuBxEd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd .marker.cross{stroke:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V1PK0lnFlIIuBxEd p{margin:0;}#mermaid-svg-V1PK0lnFlIIuBxEd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster-label text{fill:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster-label span{color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster-label span p{background-color:transparent;}#mermaid-svg-V1PK0lnFlIIuBxEd .label text,#mermaid-svg-V1PK0lnFlIIuBxEd span{fill:#333;color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .node rect,#mermaid-svg-V1PK0lnFlIIuBxEd .node circle,#mermaid-svg-V1PK0lnFlIIuBxEd .node ellipse,#mermaid-svg-V1PK0lnFlIIuBxEd .node polygon,#mermaid-svg-V1PK0lnFlIIuBxEd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .rough-node .label text,#mermaid-svg-V1PK0lnFlIIuBxEd .node .label text,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape .label,#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape .label{text-anchor:middle;}#mermaid-svg-V1PK0lnFlIIuBxEd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .rough-node .label,#mermaid-svg-V1PK0lnFlIIuBxEd .node .label,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape .label,#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape .label{text-align:center;}#mermaid-svg-V1PK0lnFlIIuBxEd .node.clickable{cursor:pointer;}#mermaid-svg-V1PK0lnFlIIuBxEd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd .arrowheadPath{fill:#333333;}#mermaid-svg-V1PK0lnFlIIuBxEd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-V1PK0lnFlIIuBxEd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-V1PK0lnFlIIuBxEd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V1PK0lnFlIIuBxEd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-V1PK0lnFlIIuBxEd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V1PK0lnFlIIuBxEd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster text{fill:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd .cluster span{color:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-V1PK0lnFlIIuBxEd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-V1PK0lnFlIIuBxEd rect.text{fill:none;stroke-width:0;}#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape p,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-V1PK0lnFlIIuBxEd .icon-shape .label rect,#mermaid-svg-V1PK0lnFlIIuBxEd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-V1PK0lnFlIIuBxEd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-V1PK0lnFlIIuBxEd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-V1PK0lnFlIIuBxEd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调度策略
事件监控
实体层
输入侧(IN方向)
输出侧(OUT方向)
数据代理
方向决定
核心:PSDEDATASYNC
outpssysdatasyncagentid
outpsdedatasetid
psdedataexpid
pssyssfpluginid
psdegridid
inpssysdatasyncagentid
psdedataimpid
createpsdeactionid
pssyssfpluginid
包含
psdeid
psdelogicid
psdedqid
eventtype
timerpolicy
实体数据同步

psdedatasync
IN(输入)

从外部接收数据
OUT(输出)

向外部发送数据
PSSYSDATASYNCAGENT

系统数据同步代理

  • FILE/KAFKA/RABBITMQ/...

  • IN/OUT/INOUT
    PSDEDATASET

输出数据集

定义输出数据范围
PSDEDATAEXP

数据导出

CSV/TSV/XLSX/JSON
PSDEGRID

导出表格

定义导出列
PSSYSSFPLUGIN

后端插件

GroupDEDataSyncOutRuntime
PSDEDATAIMP

数据导入

含导入项映射
PSDEDATAIMPITEM

导入字段映射

多个字段
PSDEACTION

导入行为

批量导入
PSSYSSFPLUGIN

后端插件

CustomDEDataImportRuntime
PSDATAENTITY

所属实体
PSDEDATAQUERY

数据查询
PSDELOGIC

处理逻辑

(数据集来源)
eventtype

1-新建 2-更新 4-删除

7=全部
timerpolicy

CRON表达式

outmode=1实时/2定时

2.2 关键属性说明

属性 说明 案例1(InStorageSync) 案例2(InboundSync)
syncdir 同步方向:IN/OUT OUT IN
eventtype 监控事件:1新建/2更新/4删除/7全部 7 7
outmode 输出模式:1实时/2定时 2(定时) -
timerpolicy CRON定时策略 定时CRON表达式 定时CRON表达式
filtermodel 过滤器模型(JSON) {"groupFields":"stor_location",...} {"file":"文件匹配模式"}
pssyssfpluginid 后端运行时插件 GroupDEDataSyncOutRuntime -

三、标准构建指南

3.1 构建步骤总览

#mermaid-svg-UoqBgqGIp6Za2h39{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-UoqBgqGIp6Za2h39 .error-icon{fill:#552222;}#mermaid-svg-UoqBgqGIp6Za2h39 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-UoqBgqGIp6Za2h39 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-UoqBgqGIp6Za2h39 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 .marker.cross{stroke:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-UoqBgqGIp6Za2h39 p{margin:0;}#mermaid-svg-UoqBgqGIp6Za2h39 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster-label text{fill:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster-label span{color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster-label span p{background-color:transparent;}#mermaid-svg-UoqBgqGIp6Za2h39 .label text,#mermaid-svg-UoqBgqGIp6Za2h39 span{fill:#333;color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .node rect,#mermaid-svg-UoqBgqGIp6Za2h39 .node circle,#mermaid-svg-UoqBgqGIp6Za2h39 .node ellipse,#mermaid-svg-UoqBgqGIp6Za2h39 .node polygon,#mermaid-svg-UoqBgqGIp6Za2h39 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .rough-node .label text,#mermaid-svg-UoqBgqGIp6Za2h39 .node .label text,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape .label,#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape .label{text-anchor:middle;}#mermaid-svg-UoqBgqGIp6Za2h39 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .rough-node .label,#mermaid-svg-UoqBgqGIp6Za2h39 .node .label,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape .label,#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape .label{text-align:center;}#mermaid-svg-UoqBgqGIp6Za2h39 .node.clickable{cursor:pointer;}#mermaid-svg-UoqBgqGIp6Za2h39 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 .arrowheadPath{fill:#333333;}#mermaid-svg-UoqBgqGIp6Za2h39 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-UoqBgqGIp6Za2h39 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-UoqBgqGIp6Za2h39 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UoqBgqGIp6Za2h39 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-UoqBgqGIp6Za2h39 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UoqBgqGIp6Za2h39 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster text{fill:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 .cluster span{color:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-UoqBgqGIp6Za2h39 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-UoqBgqGIp6Za2h39 rect.text{fill:none;stroke-width:0;}#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape p,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-UoqBgqGIp6Za2h39 .icon-shape .label rect,#mermaid-svg-UoqBgqGIp6Za2h39 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-UoqBgqGIp6Za2h39 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-UoqBgqGIp6Za2h39 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-UoqBgqGIp6Za2h39 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} OUT(输出)
IN(输入)
Step 1: 明确业务需求
Step 2: 确定同步方向
IN or OUT?
Step 3: 定义数据代理

PSSYSDATASYNCAGENT
Step 3: 定义数据代理

PSSYSDATASYNCAGENT
Step 4: 定义输出数据集

PSDEDATASET
Step 4: 定义数据导入

PSDEDATAIMP + 导入项
Step 5: 定义数据导出

PSDEDATAEXP + 导出表格
Step 5: 定义导入行为

PSDEACTION
Step 6: 定义实体数据同步

PSDEDATASYNC
Step 7: 编译验证 & 构建

3.2 输出同步(OUT方向)构建模板

groovy 复制代码
// ========== Step 1: 定义系统数据同步代理 ==========
pssysdatasyncagent(
    name: "XXX输出代理", 
    codename: "XXXOutput", 
    agenttype: "FILE",             // FILE/KAFKA/RABBITMQ/...
    psmoduleid: "System_Mgmt",     // 所属模块
    servicepath: "外部目标路径",    // 目标路径
    syncdir: "OUT",                // 输出方向
    // 文件类型可配置:
    // rawdatamode: 1,             // 直接数据模式(不附加包头)
    // topic: "topic_name"         // 消息队列主题
)
// ========== Step 2: 定义输出数据集 ==========
// 方式A:基于处理逻辑
psdedataset(
    name: "SyncToXXX", 
    codename: "SyncToXXX", 
    logicname: "XXX导出数据集", 
    psdeid: "Module.Entity", 
    psdelogicid: "Module.Entity.SyncToXXXLogic",  // 处理逻辑提供查询
    predefinedtype: "DELOGIC"
)
// 方式B:基于数据查询
// psdedataset(
//     name: "SyncToXXX", 
//     codename: "SyncToXXX", 
//     psdeid: "Module.Entity", 
//     psdedqid: "Module.Entity.DefaultQuery"
// )
// ========== Step 3: 定义数据导出 ==========
psdedataexp(
    name: "XXX数据导出", 
    codename: "SyncToXXX", 
    contenttype: "CSV",            // CSV/TSV/XLSX/JSON
    filenameformat: "前缀_{#date_fmt.format('yyyyMMddHHmmss')}.csv",
    psdegridid: "Module.Entity.ExportGrid",  // 导出表格(定义导出列)
    psdeid: "Module.Entity"
)
// ========== Step 4: 定义实体数据同步 ==========
psdedatasync(
    name: "XXX输出同步", 
    codename: "SyncToXXX", 
    syncdir: "OUT",                                    // 输出方向
    eventtype: 7,                                      // 新建+更新+删除
    outmode: 2,                                        // 2=定时输出
    timerpolicy: "定时CRON表达式",                      // CRON定时策略
    outpsdedatasetid: "Module.Entity.SyncToXXX",       // 输出数据集
    outpssysdatasyncagentid: "System_Mgmt.XXXOutput",  // 输出代理
    psdedataexpid: "Module.Entity.SyncToXXX",          // 数据导出
    psdeid: "Module.Entity",                           // 所属实体
    pssyssfpluginid: "GroupDEDataSyncOutRuntime",      // 分组输出插件
    filtermodel: "{\"groupFields\":\"field_name\"}"    // 分组字段(可选)
)

3.3 输入同步(IN方向)构建模板

groovy 复制代码
// ========== Step 1: 定义系统数据同步代理 ==========
pssysdatasyncagent(
    name: "XXX输入代理", 
    codename: "XXXInput", 
    agenttype: "FILE",             // FILE/KAFKA/RABBITMQ/...
    psmoduleid: "System_Mgmt", 
    servicepath: "外部共享文件路径",  // 源路径
    syncdir: "IN",                 // 输入方向
    // 消息队列场景:
    // groupid: "consumer_group",  // 消费组
    // topic: "topic_name"
)
// ========== Step 2: 定义实体导入行为 ==========
// 需先定义实体的批量导入行为 PSDEACTION
// ========== Step 3: 定义数据导入 ==========
psdedataimp(
    name: "XXX数据导入", 
    codename: "XXXImport", 
    contenttype: "TSV",                               // CSV/TSV/XLSX/JSON
    createpsdeactionid: "Module.Entity.BatchImport",  // 批量导入行为
    stopwhenerror: 0,                                 // 出错不中止
    enablecustomized: 1,                              // 支持定制
    psdeid: "Module.Entity", 
    pssyssfpluginid: "CustomDEDataImportRuntime"      // 自定义导入插件
){
    // 导入字段映射(每个字段对应一个实体属性)
    psdedataimpitem(
        id: "field_code", 
        name: "field_code", 
        caption: "字段标题", 
        keyflag: 0,                // 1=识别属性(用于判断新建或更新)
        ordervalue: 1, 
        psdefid: "Module.Entity.FIELD_NAME"
    )
    // ... 更多字段
}
// ========== Step 4: 定义实体数据同步 ==========
psdedatasync(
    name: "XXX输入同步", 
    codename: "XXXInputSync", 
    syncdir: "IN",                                    // 输入方向
    eventtype: 7,                                      // 全事件
    inpssysdatasyncagentid: "System_Mgmt.XXXInput",    // 输入代理
    psdedataimpid: "Module.Entity.XXXImport",          // 数据导入
    psdeid: "Module.Entity",                           // 所属实体
    filtermodel: "{\"file\":\"文件匹配模式\"}",        // 文件过滤模式
    timerpolicy: "定时CRON表达式"                       // 每天定时执行
)

3.4 关键设计要点

设计维度 说明
同步方向 syncdir=IN为输入(从外部接收),OUT为输出(向外部发送)
事件类型 eventtype按位组合:新建=1、更新=2、删除=4,全事件=7
输出模式 outmode=1实时触发 / outmode=2定时触发(需配置timerpolicy
数据代理类型 agenttype支持 FILE(文件)、KAFKA、RABBITMQ、FTP、SFTP、SMB、INTERNAL(内部通讯)等
文件过滤 IN方向通过filtermodelfile属性指定文件名匹配模式
分组输出 OUT方向通过filtermodelgroupFields指定分组字段,实现按字段分组输出多个文件
后端插件 输出同步常用GroupDEDataSyncOutRuntime,输入同步常用CustomDEDataImportRuntime
导入识别 导入项keyflag=1标记识别属性,系统根据识别属性判断新建还是更新
CRON表达式 格式:秒 分 时 日 月 周 年,如定时CRON表达式

3.5 典型应用场景对照

场景 方向 代理类型 数据格式 插件 案例参考
外部文件回写 OUT FILE(FTP) CSV GroupDEDataSyncOutRuntime InStorageSync
外部文件读取 IN FILE(SMB) TSV CustomDEDataImportRuntime InboundSync
消息队列发送 OUT KAFKA JSON - -
消息队列消费 IN KAFKA JSON - -
内部组件通讯 INOUT INTERNAL - - -