首次提交: OnebotCatalog 项目代码与文档(含 NX 按需生成服务二期、后台、一键启动)

This commit is contained in:
wangruiguo
2026-09-03 17:55:45 +08:00
commit fafa86d3a6
241 changed files with 78656 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
# 将数据表 JPEG 包装成极简单页 A4 PDF (DCTDecode 直嵌, 字节级 xref 偏移)
# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File tools\gen-pdf.ps1
# 说明: 中文内容以图片形式嵌入, 规避 PDF 中文字体嵌入问题; 结构最小化, 主流阅读器可打开。
param(
[string]$Jpg,
[string]$Pdf
)
Add-Type -AssemblyName System.Drawing
$img = [System.Drawing.Image]::FromFile($Jpg)
$w = $img.Width
$h = $img.Height
$img.Dispose()
$jpgBytes = [System.IO.File]::ReadAllBytes($Jpg)
$chunks = New-Object System.Collections.Generic.List[byte[]]
$offsets = New-Object System.Collections.Generic.List[int]
$pos = 0
function Add-Ascii([string]$t) {
$b = [System.Text.Encoding]::ASCII.GetBytes($t)
$chunks.Add($b)
$script:pos += $b.Length
}
function Mark-Obj() { $offsets.Add($script:pos) }
$imgLen = $jpgBytes.Length + 1
$content = 'q 595.28 0 0 841.89 0 0 cm /Im0 Do Q'
$contentLen = $content.Length + 1
Add-Ascii "%PDF-1.4`n"
Mark-Obj; Add-Ascii "1 0 obj<< /Type /Catalog /Pages 2 0 R >>endobj`n"
Mark-Obj; Add-Ascii "2 0 obj<< /Type /Pages /Kids [3 0 R] /Count 1 >>endobj`n"
Mark-Obj; Add-Ascii "3 0 obj<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595.28 841.89] /Resources << /XObject << /Im0 4 0 R >> >> /Contents 5 0 R >>endobj`n"
Mark-Obj; Add-Ascii "4 0 obj<< /Type /XObject /Subtype /Image /Width $w /Height $h /ColorSpace /DeviceRGB /BitsPerComponent 8 /Filter /DCTDecode /Length $imgLen >>stream`n"
$chunks.Add($jpgBytes); $pos += $jpgBytes.Length
Add-Ascii "`nendstream`nendobj`n"
Mark-Obj; Add-Ascii "5 0 obj<< /Length $contentLen >>stream`n"
Add-Ascii "$content`nendstream`nendobj`n"
$xrefOffset = $pos
$sb = New-Object System.Text.StringBuilder
[void]$sb.Append("xref`n0 6`n0000000000 65535 f `n")
foreach ($off in $offsets) {
[void]$sb.Append(("{0:0000000000} {1:00000} n `n" -f $off, 0))
}
Add-Ascii $sb.ToString()
Add-Ascii ("trailer`n<< /Size 6 /Root 1 0 R >>`nstartxref`n" + $xrefOffset + "`n%%EOF`n")
$fs = [System.IO.File]::Create($Pdf)
foreach ($b in $chunks) { $fs.Write($b, 0, $b.Length) }
$fs.Close()
# ---- 自检: startxref 指向 xref, 且每个对象偏移处是 "N 0 obj" ----
$check = [System.IO.File]::ReadAllBytes($Pdf)
$text = [System.Text.Encoding]::ASCII.GetString($check)
$m = [regex]::Match($text, 'startxref\s+(\d+)')
if (-not $m.Success) { Write-Output ("FAIL: 无 startxref - " + $Pdf); return }
$xref = [int64]$m.Groups[1].Value
$ok = ($text.Substring($xref, 4) -eq 'xref')
$lines = $text.Substring($xref + 4).Split("`n")
# xref 段: 行0='xref', 行1='0 6', 行2=第0号自由条目, 行3..7=对象1..5
for ($i = 3; $i -lt 8; $i++) {
$entry = $lines[$i]
$objNum = $i - 2
if ($entry -match '^(\d{10}) 00000 n') {
$off2 = [int64]$entry.Substring(0, 10)
if ($text.Substring($off2, 10) -notmatch ('^' + $objNum + ' 0 obj')) { $ok = $false }
} else { $ok = $false }
}
if ($ok) { Write-Output ("OK: " + $Pdf + " (" + (($check.Length / 1KB).ToString('0') + " KB)")) }
else { Write-Output ("FAIL: xref 校验失败 - " + $Pdf) }