XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWorkflow

【WinUI】XFE基于windows的工作流

公开
关注 0 Fork 0 Star 0
UTF-8
param()
$ErrorActionPreference = 'Stop'
$taskRepo = Split-Path -Parent $PSScriptRoot
$taskSamples = Join-Path $taskRepo 'samples/workflows'
$taskUtf8 = [Text.UTF8Encoding]::new($false)

function New-Node($id, $capability, $name, $parameters = @{}, $x = 160, $y = 180) {
    return [ordered]@{ id = $id; capabilityId = "core.$capability"; name = $name; x = $x; y = $y; parameters = $parameters }
}
function New-Sequence($nodes) {
    $edges = @()
    for ($i = 0; $i -lt $nodes.Count - 1; $i++) {
        $edges += [ordered]@{ fromNode = $nodes[$i].id; fromPort = 'next'; toNode = $nodes[$i + 1].id; toPort = 'in'; kind = 'Execution' }
    }
    return [ordered]@{ nodes = @($nodes); edges = $edges }
}
function Add-Wire($graph, $from, $output, $to, $targetPort) {
    $graph.edges += [ordered]@{ fromNode = $from; fromPort = $output; toNode = $to; toPort = $targetPort; kind = 'Data' }
}
function Save-Sample($file, $name, $description, $graph, $inputs = @(), $defaults = @{}, $outputs = @()) {
    $workflow = [ordered]@{
        schemaVersion = 1; id = "sample-$file"; name = $name; description = $description; enabled = $false
        kind = 'Graph'; graph = $graph; inputs = @($inputs); inputDefaults = $defaults; outputs = @($outputs)
        variables = @{}; pluginVersions = @{}; triggers = @(); modifiedAt = '2026-10-13T00:00:00+08:00'
    }
    $json = ($workflow | ConvertTo-Json -Depth 100) + [Environment]::NewLine
    [IO.File]::WriteAllText((Join-Path $taskSamples "$file.json"), $json, $taskUtf8)
    $stream = [IO.File]::Open((Join-Path $taskSamples "$file.xfeworkflow"), [IO.FileMode]::Create)
    try {
        $archive = [IO.Compression.ZipArchive]::new($stream, [IO.Compression.ZipArchiveMode]::Create, $true)
        try {
            $entry = $archive.CreateEntry('workflow.json')
            $writer = [IO.StreamWriter]::new($entry.Open(), $taskUtf8)
            try { $writer.Write($json) } finally { $writer.Dispose() }
        } finally { $archive.Dispose() }
    } finally { $stream.Dispose() }
}

$concat = New-Sequence @(
    (New-Node 'text-start' 'start' '开始'),
    (New-Node 'text-concat' 'text.concat' '拼接两段文本' @{ separator = '' } 620),
    (New-Node 'text-log' 'log' '输出拼接结果' @{} 1080),
    (New-Node 'text-end' 'end' '结束' @{} 1540)
)
Add-Wire $concat 'text-start' 'left' 'text-concat' 'left'
Add-Wire $concat 'text-start' 'right' 'text-concat' 'right'
Add-Wire $concat 'text-concat' 'value' 'text-log' 'message'
Add-Wire $concat 'text-concat' 'value' 'text-end' 'result'
Save-Sample 'basic-text-concat' '基础节点 · 文本拼接' '将工作流输入的两段文本通过连线拼接,只输出一条明确的日志。分隔符可在拼接节点设置;原输入、空白和表情保持不变。无需插件。' $concat @(
    @{ name = 'left'; label = '左文本'; type = 'String' }, @{ name = 'right'; label = '右文本'; type = 'String' }
) @{ left = '你好,'; right = 'XFEWorkflow 🌚' } @(@{ name = 'result'; label = '拼接文本'; type = 'String' })

$filter = New-Sequence @(
    (New-Node 'filter-start' 'start' '开始'),
    (New-Node 'contact-filter' 'array.filter' '筛选多个联系人 ID' @{ path = 'id'; operator = 'in'; right = @('1001', '1003') } 620),
    (New-Node 'contact-names' 'array.mapField' '提取联系人名称' @{ path = 'displayName' } 1080),
    (New-Node 'names-join' 'text.join' '连接名称' @{ separator = '、' } 1540),
    (New-Node 'names-log' 'log' '输出名称列表' @{} 2000),
    (New-Node 'filter-end' 'end' '结束' @{} 2460)
)
Add-Wire $filter 'filter-start' 'contacts' 'contact-filter' 'items'
Add-Wire $filter 'contact-filter' 'value' 'contact-names' 'items'
Add-Wire $filter 'contact-names' 'value' 'names-join' 'items'
Add-Wire $filter 'names-join' 'value' 'names-log' 'message'
Add-Wire $filter 'names-join' 'value' 'filter-end' 'result'
Add-Wire $filter 'contact-filter' 'value' 'filter-end' 'contacts'
Save-Sample 'basic-array-filter-join' '基础节点 · 筛选联系人并拼接名称' '离线演示数组筛选、提取字段和文本连接。筛选节点 right 中填写多个联系人 ID;接入企业微信时把搜索缓存联系人的 contacts 数组连到筛选节点 items。无需消息表达式。' $filter @(
    @{ name = 'contacts'; label = '联系人数组'; type = 'Array' }
) @{ contacts = @(
    @{ id = '1001'; displayName = '张三 🌚' }, @{ id = '1002'; displayName = '李四 👍🏽' }, @{ id = '1003'; displayName = '王五 👨‍👩‍👧‍👦' }
) } @(@{ name = 'result'; label = '名称文本'; type = 'String' }, @{ name = 'contacts'; label = '筛选结果'; type = 'Array' })

$forBody = New-Sequence @(
    (New-Node 'for-body-start' 'start' '本轮开始'),
    (New-Node 'for-current' 'foreach.current' '当前计数值' @{} 620),
    (New-Node 'for-number' 'convert.number' '转换为数字' @{} 1080),
    (New-Node 'for-multiply' 'math.multiply' '乘以十' @{ right = 10 } 1540),
    (New-Node 'for-log' 'log' '输出计算结果' @{} 2000),
    (New-Node 'for-body-end' 'end' '本轮返回' @{} 2460)
)
Add-Wire $forBody 'for-current' 'item' 'for-number' 'value'
Add-Wire $forBody 'for-number' 'value' 'for-multiply' 'left'
Add-Wire $forBody 'for-multiply' 'value' 'for-log' 'message'
Add-Wire $forBody 'for-multiply' 'value' 'for-body-end' 'result'
$forNode = New-Node 'for-loop' 'for' '从一开始计数三次' @{ start = 1; count = 3; step = 1 } 620
$forNode.children = @{ body = $forBody }
$forGraph = New-Sequence @((New-Node 'for-start' 'start' '开始'), $forNode, (New-Node 'for-end' 'end' '结束' @{} 1080))
Add-Wire $forGraph 'for-loop' 'results' 'for-end' 'result'
Save-Sample 'basic-for-numbers' '基础节点 · 计数循环与数学运算' '计数值 1、2、3 乘以 10,通过连线输出 10、20、30。进入 body 子图可设置断点并用 F10/F11 调试;不输出循环开始或结束。' $forGraph

$condition = New-Sequence @(
    (New-Node 'while-condition-start' 'start' '判断开始'),
    (New-Node 'while-counter-read' 'variable.get' '读取当前计数' @{ name = 'counter' } 620),
    (New-Node 'while-counter-number' 'convert.number' '转换为数字' @{} 1080),
    (New-Node 'while-compare' 'compare.lt' '小于三' @{ right = 3 } 1540),
    (New-Node 'while-condition-end' 'end' '返回布尔判断' @{} 2000)
)
Add-Wire $condition 'while-counter-read' 'value' 'while-counter-number' 'value'
Add-Wire $condition 'while-counter-number' 'value' 'while-compare' 'left'
Add-Wire $condition 'while-compare' 'value' 'while-condition-end' 'result'
$whileBody = New-Sequence @(
    (New-Node 'while-body-start' 'start' '本轮开始'),
    (New-Node 'while-increment' 'variable.increment' '计数加一' @{ name = 'counter'; amount = 1 } 620),
    (New-Node 'while-log' 'log' '输出当前计数' @{} 1080),
    (New-Node 'while-body-end' 'end' '本轮返回' @{} 1540)
)
Add-Wire $whileBody 'while-increment' 'value' 'while-log' 'message'
Add-Wire $whileBody 'while-increment' 'value' 'while-body-end' 'result'
$whileNode = New-Node 'while-loop' 'while' '每轮判断后循环' @{ maxIterations = 10 } 1080
$whileNode.children = @{ body = $whileBody; condition = $condition }
$whileGraph = New-Sequence @(
    (New-Node 'while-start' 'start' '开始'),
    (New-Node 'while-initialize' 'set' '计数初始为零' @{ name = 'counter'; value = 0 } 620),
    $whileNode,
    (New-Node 'while-final-read' 'variable.get' '读取最终计数' @{ name = 'counter' } 1540),
    (New-Node 'while-end' 'end' '结束' @{} 2000)
)
Add-Wire $whileGraph 'while-final-read' 'value' 'while-end' 'result'
Save-Sample 'basic-while-wired-condition' '基础节点 · 连线判断条件循环' '不填写变量表达式。condition 子图每轮读取 counter 并判断是否小于 3;body 递增并输出 1、2、3。所有数值通过数据连线传递,结束返回 3。' $whileGraph