Add-Type -AssemblyName System.Drawing $desktop = [Environment]::GetFolderPath("Desktop") $output = Join-Path $desktop "供应监测决策流程图.png" $width = 3600 $height = 1850 $bmp = New-Object System.Drawing.Bitmap($width, $height) $g = [System.Drawing.Graphics]::FromImage($bmp) $g.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias $g.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::ClearTypeGridFit $g.Clear([System.Drawing.Color]::White) $fontFamily = "Microsoft YaHei" $font = New-Object System.Drawing.Font($fontFamily, 28, [System.Drawing.FontStyle]::Regular) $boldFont = New-Object System.Drawing.Font($fontFamily, 30, [System.Drawing.FontStyle]::Bold) $titleFont = New-Object System.Drawing.Font($fontFamily, 44, [System.Drawing.FontStyle]::Bold) $labelFont = New-Object System.Drawing.Font($fontFamily, 24, [System.Drawing.FontStyle]::Bold) $black = [System.Drawing.Color]::FromArgb(35, 35, 35) $lineColor = [System.Drawing.Color]::FromArgb(72, 92, 120) $blueFill = [System.Drawing.Color]::FromArgb(235, 244, 255) $greenFill = [System.Drawing.Color]::FromArgb(235, 250, 241) $yellowFill = [System.Drawing.Color]::FromArgb(255, 249, 225) $redFill = [System.Drawing.Color]::FromArgb(255, 238, 238) $grayFill = [System.Drawing.Color]::FromArgb(247, 249, 252) $strokeBlue = [System.Drawing.Color]::FromArgb(69, 125, 197) $strokeGreen = [System.Drawing.Color]::FromArgb(46, 140, 88) $strokeYellow = [System.Drawing.Color]::FromArgb(196, 142, 35) $strokeRed = [System.Drawing.Color]::FromArgb(196, 76, 76) $strokeGray = [System.Drawing.Color]::FromArgb(130, 145, 165) function New-Pen($color, $width) { $pen = New-Object System.Drawing.Pen($color, $width) $pen.StartCap = [System.Drawing.Drawing2D.LineCap]::Round $pen.EndCap = [System.Drawing.Drawing2D.LineCap]::Round return $pen } $linePen = New-Pen $lineColor 4 $arrowPen = New-Pen $lineColor 4 $arrowPen.CustomEndCap = New-Object System.Drawing.Drawing2D.AdjustableArrowCap(8, 8) $textBrush = New-Object System.Drawing.SolidBrush($black) $labelBrush = New-Object System.Drawing.SolidBrush([System.Drawing.Color]::FromArgb(55, 75, 100)) $sf = New-Object System.Drawing.StringFormat $sf.Alignment = [System.Drawing.StringAlignment]::Center $sf.LineAlignment = [System.Drawing.StringAlignment]::Center $sf.FormatFlags = [System.Drawing.StringFormatFlags]::LineLimit function Draw-RoundRect($graphics, $rect, $radius, $fill, $stroke) { $path = New-Object System.Drawing.Drawing2D.GraphicsPath $d = $radius * 2 $path.AddArc($rect.X, $rect.Y, $d, $d, 180, 90) $path.AddArc($rect.Right - $d, $rect.Y, $d, $d, 270, 90) $path.AddArc($rect.Right - $d, $rect.Bottom - $d, $d, $d, 0, 90) $path.AddArc($rect.X, $rect.Bottom - $d, $d, $d, 90, 90) $path.CloseFigure() $graphics.FillPath((New-Object System.Drawing.SolidBrush($fill)), $path) $graphics.DrawPath((New-Object System.Drawing.Pen($stroke, 4)), $path) } function Draw-Node($id, $x, $y, $w, $h, $text, $fill, $stroke) { $rect = New-Object System.Drawing.RectangleF($x, $y, $w, $h) Draw-RoundRect $g $rect 22 $fill $stroke $inner = New-Object System.Drawing.RectangleF($x + 18, $y + 10, $w - 36, $h - 20) $g.DrawString($text, $font, $textBrush, $inner, $sf) $script:nodes[$id] = $rect } function Draw-Diamond($id, $x, $y, $w, $h, $text, $fill, $stroke) { $path = New-Object System.Drawing.Drawing2D.GraphicsPath $path.AddPolygon(@( (New-Object System.Drawing.PointF(($x + $w / 2), $y)), (New-Object System.Drawing.PointF(($x + $w), ($y + $h / 2))), (New-Object System.Drawing.PointF(($x + $w / 2), ($y + $h))), (New-Object System.Drawing.PointF($x, ($y + $h / 2))) )) $g.FillPath((New-Object System.Drawing.SolidBrush($fill)), $path) $g.DrawPath((New-Object System.Drawing.Pen($stroke, 4)), $path) $inner = New-Object System.Drawing.RectangleF($x + 40, $y + 18, $w - 80, $h - 36) $g.DrawString($text, $boldFont, $textBrush, $inner, $sf) $script:nodes[$id] = New-Object System.Drawing.RectangleF($x, $y, $w, $h) } function Center($rect) { return New-Object System.Drawing.PointF(($rect.X + $rect.Width / 2), ($rect.Y + $rect.Height / 2)) } function EdgePoint($rect, $side) { switch ($side) { "L" { return New-Object System.Drawing.PointF($rect.X, ($rect.Y + $rect.Height / 2)) } "R" { return New-Object System.Drawing.PointF(($rect.X + $rect.Width), ($rect.Y + $rect.Height / 2)) } "T" { return New-Object System.Drawing.PointF(($rect.X + $rect.Width / 2), $rect.Y) } "B" { return New-Object System.Drawing.PointF(($rect.X + $rect.Width / 2), ($rect.Y + $rect.Height)) } } } function Draw-Arrow($from, $fromSide, $to, $toSide, $label = "") { $a = EdgePoint $nodes[$from] $fromSide $b = EdgePoint $nodes[$to] $toSide $g.DrawLine($arrowPen, $a, $b) if ($label -ne "") { $mx = ($a.X + $b.X) / 2 $my = ($a.Y + $b.Y) / 2 $labelRect = New-Object System.Drawing.RectangleF($mx - 42, $my - 32, 84, 44) $g.FillRectangle([System.Drawing.Brushes]::White, $labelRect) $g.DrawString($label, $labelFont, $labelBrush, $labelRect, $sf) } } function Draw-PolylineArrow($points, $label = "", $labelX = 0, $labelY = 0) { for ($i = 0; $i -lt $points.Count - 2; $i++) { $g.DrawLine($linePen, $points[$i], $points[$i + 1]) } $g.DrawLine($arrowPen, $points[$points.Count - 2], $points[$points.Count - 1]) if ($label -ne "") { $labelRect = New-Object System.Drawing.RectangleF($labelX - 42, $labelY - 32, 84, 44) $g.FillRectangle([System.Drawing.Brushes]::White, $labelRect) $g.DrawString($label, $labelFont, $labelBrush, $labelRect, $sf) } } $nodes = @{} $titleRect = New-Object System.Drawing.RectangleF(0, 35, $width, 70) $g.DrawString("供应监测补货决策流程", $titleFont, $textBrush, $titleRect, $sf) Draw-Node "A" 80 735 500 180 "更新数据`n预测需求 / 现有库存 / 在途库存`n半成品库存 / 已下单未要求来货" $blueFill $strokeBlue Draw-Node "B" 700 735 430 180 "核算现有可用量`n现有库存 + 半成品可组装量" $blueFill $strokeBlue Draw-Diamond "C" 1240 680 380 290 "现有可用量`n是否覆盖需求?" $yellowFill $strokeYellow Draw-Node "D" 1780 330 360 140 "现有库存可覆盖" $greenFill $strokeGreen Draw-Diamond "E" 2300 285 360 230 "是否需要`n组装半成品?" $yellowFill $strokeYellow Draw-Node "F" 2830 190 340 130 "无需来货 / 下单" $greenFill $strokeGreen Draw-Node "G" 2830 420 340 150 "安排半成品组装`n转为成品库存" $greenFill $strokeGreen Draw-Node "H" 1780 830 360 150 "现有可用量不足`n计算缺口" $redFill $strokeRed Draw-Diamond "I" 2300 795 360 230 "在途库存`n是否覆盖缺口?" $yellowFill $strokeYellow Draw-Node "J" 2830 710 340 150 "跟进在途到货`n更新到货计划" $greenFill $strokeGreen Draw-Node "K" 2830 960 340 130 "在途后仍有缺口" $redFill $strokeRed Draw-Diamond "L" 2300 1210 360 250 "已下单未要求来货`n是否覆盖缺口?" $yellowFill $strokeYellow Draw-Node "M" 2830 1180 340 160 "安排来货`n通知供应商发货 / 到货" $greenFill $strokeGreen Draw-Node "N" 1780 1275 360 160 "已下单量仍不足`n计算新增下单量" $redFill $strokeRed Draw-Diamond "O" 1240 1225 380 230 "是否急需?" $yellowFill $strokeYellow Draw-Node "P" 700 1125 430 150 "新增加急下单`n优先排产" $redFill $strokeRed Draw-Node "Q" 700 1390 430 130 "新增常规下单" $grayFill $strokeGray Draw-Node "S" 2830 610 340 130 "更新组装计划`n回写库存跟踪" $blueFill $strokeBlue Draw-Node "T" 2830 890 340 130 "更新在途到货计划`n回写库存跟踪" $blueFill $strokeBlue Draw-Node "U" 2830 1385 340 130 "更新来货计划`n回写库存跟踪" $blueFill $strokeBlue Draw-Node "V" 700 1610 430 130 "更新下单计划`n回写库存跟踪" $blueFill $strokeBlue Draw-Node "R" 1780 1610 420 130 "持续跟踪销售与库存" $greenFill $strokeGreen Draw-Arrow "A" "R" "B" "L" Draw-Arrow "B" "R" "C" "L" Draw-Arrow "C" "R" "D" "L" "是" Draw-Arrow "C" "R" "H" "L" "否" Draw-Arrow "D" "R" "E" "L" Draw-Arrow "E" "R" "F" "L" "否" Draw-Arrow "E" "R" "G" "L" "是" Draw-Arrow "H" "R" "I" "L" Draw-Arrow "I" "R" "J" "L" "是" Draw-Arrow "I" "R" "K" "L" "否" Draw-PolylineArrow @((EdgePoint $nodes["K"] "B"), (New-Object System.Drawing.PointF(3000, 1130)), (New-Object System.Drawing.PointF(2480, 1130)), (EdgePoint $nodes["L"] "T")) Draw-Arrow "L" "R" "M" "L" "是" Draw-PolylineArrow @((EdgePoint $nodes["L"] "L"), (New-Object System.Drawing.PointF(2160, 1335)), (EdgePoint $nodes["N"] "R")) "否" 2200 1335 Draw-Arrow "N" "L" "O" "R" Draw-Arrow "O" "L" "P" "R" "是" Draw-PolylineArrow @((EdgePoint $nodes["O"] "B"), (New-Object System.Drawing.PointF(1430, 1455)), (EdgePoint $nodes["Q"] "R")) "否" 1300 1455 Draw-PolylineArrow @((EdgePoint $nodes["G"] "B"), (New-Object System.Drawing.PointF(3000, 595)), (EdgePoint $nodes["S"] "T")) Draw-PolylineArrow @((EdgePoint $nodes["J"] "B"), (New-Object System.Drawing.PointF(3000, 875)), (EdgePoint $nodes["T"] "T")) Draw-PolylineArrow @((EdgePoint $nodes["M"] "B"), (New-Object System.Drawing.PointF(3000, 1365)), (EdgePoint $nodes["U"] "T")) Draw-Arrow "P" "B" "V" "T" Draw-Arrow "Q" "B" "V" "T" Draw-PolylineArrow @((EdgePoint $nodes["F"] "B"), (New-Object System.Drawing.PointF(3000, 1645)), (EdgePoint $nodes["R"] "R")) Draw-PolylineArrow @((EdgePoint $nodes["S"] "B"), (New-Object System.Drawing.PointF(3000, 1665)), (EdgePoint $nodes["R"] "R")) Draw-PolylineArrow @((EdgePoint $nodes["T"] "B"), (New-Object System.Drawing.PointF(3000, 1680)), (EdgePoint $nodes["R"] "R")) Draw-PolylineArrow @((EdgePoint $nodes["U"] "B"), (New-Object System.Drawing.PointF(3000, 1700)), (EdgePoint $nodes["R"] "R")) Draw-Arrow "V" "R" "R" "L" $bmp.Save($output, [System.Drawing.Imaging.ImageFormat]::Png) $g.Dispose() $bmp.Dispose() Write-Output $output