@agile-team/mach-report 2.10.0 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +6 -2
  2. package/dist/ExcelBindingWizard-LWX6G1A2.js +1465 -0
  3. package/dist/ExcelBindingWizard-a4kslPHF.cjs +1 -0
  4. package/dist/ParamEditor-BLaE5q5W.js +522 -0
  5. package/dist/ParamEditor-MBBC7lUE.cjs +1 -0
  6. package/dist/ReportBatchPanel-B5ClP9tm.js +350 -0
  7. package/dist/ReportBatchPanel-Dc-SDkYA.cjs +1 -0
  8. package/dist/ReportPreview-DWXROHBP.cjs +6 -0
  9. package/dist/ReportPreview-DiNXhQI0.js +4138 -0
  10. package/dist/ReportTemplateLibrary-5fk5CQBO.cjs +1 -0
  11. package/dist/ReportTemplateLibrary-BZB-XWjj.js +311 -0
  12. package/dist/RuleEditor-C2QsOHOs.cjs +1 -0
  13. package/dist/RuleEditor-D9wQHrkf.js +2024 -0
  14. package/dist/TemplateReviewPanel-BKofGrV9.js +222 -0
  15. package/dist/TemplateReviewPanel-DwtOcLue.cjs +1 -0
  16. package/dist/analytics.cjs +1 -1
  17. package/dist/analytics.d.cts +2 -0
  18. package/dist/analytics.d.ts +2 -0
  19. package/dist/analytics.js +29 -29
  20. package/dist/batch-Bt3Fd27Z.cjs +1 -0
  21. package/dist/batch-mRqhhhjt.js +364 -0
  22. package/dist/computed-Bvk0W15F.js +521 -0
  23. package/dist/computed-CGV2a809.cjs +1 -0
  24. package/dist/config-B612mw0x.js +525 -0
  25. package/dist/config-BRoLo2oj.cjs +1 -0
  26. package/dist/designer.cjs +2 -2
  27. package/dist/designer.d.cts +730 -9
  28. package/dist/designer.d.ts +730 -9
  29. package/dist/designer.js +2093 -1785
  30. package/dist/index.cjs +8 -8
  31. package/dist/index.d.cts +161 -3
  32. package/dist/index.d.ts +161 -3
  33. package/dist/index.js +486 -431
  34. package/dist/injection-keys-Db_DyLkm.cjs +1 -0
  35. package/dist/injection-keys-e85udZCp.js +7 -0
  36. package/dist/list-cell-BuYn4tGF.cjs +1 -0
  37. package/dist/{list-cell-Dxyi7DOw.js → list-cell-ClFra1zS.js} +54 -40
  38. package/dist/matrix-DVyWiYsd.cjs +1 -0
  39. package/dist/matrix-yZsGnldA.js +227 -0
  40. package/dist/param-validation-BlHHXs6u.js +153 -0
  41. package/dist/param-validation-DCK039V1.cjs +1 -0
  42. package/dist/pdf.cjs +25 -25
  43. package/dist/pdf.d.cts +3 -0
  44. package/dist/pdf.d.ts +3 -0
  45. package/dist/pdf.js +677 -677
  46. package/dist/plugin-BDTU4D94.cjs +1 -0
  47. package/dist/plugin-Cd5G2QQn.js +22 -0
  48. package/dist/region-binding-workflow-CXDmt9Bs.js +977 -0
  49. package/dist/region-binding-workflow-DhQvu1co.cjs +3 -0
  50. package/dist/{report-params-B_VCihAh.js → report-params-B44imUd4.js} +1 -1
  51. package/dist/{report-params-CjWrjPl6.cjs → report-params-SJfhKgaX.cjs} +1 -1
  52. package/dist/server/node.d.cts +5 -2
  53. package/dist/server/node.d.ts +5 -2
  54. package/dist/server-node.cjs +1 -1
  55. package/dist/server-node.js +87 -87
  56. package/dist/server.cjs +1 -1
  57. package/dist/server.d.cts +201 -2
  58. package/dist/server.d.ts +201 -2
  59. package/dist/server.js +557 -658
  60. package/dist/style.css +1 -1
  61. package/dist/template-registry-WNXdkiET.js +506 -0
  62. package/dist/template-registry-ukBGlm8N.cjs +1 -0
  63. package/dist/template-review-BXp2oyqg.cjs +1 -0
  64. package/dist/template-review-BdcXSYbx.js +1616 -0
  65. package/dist/tree-BX380Rr7.cjs +1 -0
  66. package/dist/tree-CqcQ99NM.js +172 -0
  67. package/dist/{validate-UUy9yP4K.js → validate-7s0yn6ii.js} +44 -44
  68. package/dist/validate-DsRiNw8h.cjs +1 -0
  69. package/dist/vue/async.d.cts +93 -4
  70. package/dist/vue/async.d.ts +93 -4
  71. package/dist/vue/index.d.cts +145 -7
  72. package/dist/vue/index.d.ts +145 -7
  73. package/dist/vue-async.cjs +1 -1
  74. package/dist/vue-async.js +5 -5
  75. package/dist/vue.cjs +1 -1
  76. package/dist/vue.js +116 -113
  77. package/dist/{workbook-session-B-bW5_yR.js → workbook-session-BKOTwcoq.js} +1 -1
  78. package/dist/{workbook-session-D7RtdNo0.cjs → workbook-session-CLYLhZWu.cjs} +1 -1
  79. package/dist/worker.cjs +1 -1
  80. package/dist/worker.d.cts +5 -2
  81. package/dist/worker.d.ts +5 -2
  82. package/dist/worker.js +1 -1
  83. package/dist/xlsx.cjs +3 -3
  84. package/dist/xlsx.d.cts +129 -2
  85. package/dist/xlsx.d.ts +129 -2
  86. package/dist/xlsx.js +336 -242
  87. package/package.json +1 -1
  88. package/dist/ExcelBindingWizard-CF7RplWm.cjs +0 -1
  89. package/dist/ExcelBindingWizard-qhwEderR.js +0 -842
  90. package/dist/ReportPreview-BE1tCHqE.js +0 -4604
  91. package/dist/ReportPreview-QKRKQOe3.cjs +0 -6
  92. package/dist/RuleEditor-BA36yIV6.js +0 -1723
  93. package/dist/RuleEditor-CczJ6mJm.cjs +0 -1
  94. package/dist/TemplateReviewPanel-CHi4Alqa.cjs +0 -1
  95. package/dist/TemplateReviewPanel-Dz0G5o83.js +0 -217
  96. package/dist/binding-preview-BWsdf_z2.cjs +0 -2
  97. package/dist/binding-preview-DILq0-0f.js +0 -649
  98. package/dist/decimal-CI1OAczk.js +0 -87
  99. package/dist/decimal-CQA0xJex.cjs +0 -1
  100. package/dist/list-cell-CyM1ZlRN.cjs +0 -1
  101. package/dist/matrix-BbXarwyk.js +0 -661
  102. package/dist/matrix-Cm65WLLP.cjs +0 -1
  103. package/dist/param-validation-BWNjLcN0.js +0 -116
  104. package/dist/param-validation-CiTxFeZ8.cjs +0 -1
  105. package/dist/plugin-CThk42vJ.cjs +0 -1
  106. package/dist/plugin-tGn7-5oF.js +0 -25
  107. package/dist/template-registry-CGWTLtIA.cjs +0 -1
  108. package/dist/template-registry-DzlQs3OF.js +0 -434
  109. package/dist/template-review-D1RoNCPw.cjs +0 -1
  110. package/dist/template-review-fnteXRng.js +0 -1473
  111. package/dist/validate-Bf6ccFr2.cjs +0 -1
@@ -0,0 +1,3 @@
1
+ "use strict";const F=require("./dataset-BkRmwgeJ.cjs"),R=require("./template-registry-ukBGlm8N.cjs"),N=require("./grid-geometry-CZ_cYB6O.cjs");function S(t){let e="";for(let o=t;o>0;o=Math.floor((o-1)/26))e=String.fromCharCode(65+(o-1)%26)+e;return e}function M(t){return`${S(t.left)}${t.top}:${S(t.right)}${t.bottom}`}function _(t){let e=0;for(const o of t.toUpperCase())e=e*26+o.charCodeAt(0)-64;return e}function d(t){if(typeof t!="string")throw new Error("Excel 范围应为 A1:B20 格式的字符串");const e=/^\$?([A-Z]{1,3})\$?([1-9]\d{0,6})(?::\$?([A-Z]{1,3})\$?([1-9]\d{0,6}))?$/i.exec(t.trim());if(!e)throw new Error(`Excel 范围无效:${t}`);const o={left:_(e[1]),top:Number(e[2]),right:_(e[3]??e[1]),bottom:Number(e[4]??e[2])};if(o.right<o.left||o.bottom<o.top||o.right>16384||o.bottom>1048576)throw new Error(`Excel 范围超出边界或顺序无效:${t}`);return o}function mt(t,e){if(e!==void 0)return d(e);const o=t.model.rows??[];if(!o.length)return{top:1,left:1,bottom:1,right:1};const r={top:1/0,left:1/0,bottom:1,right:1};for(const n of o)r.top=Math.min(r.top,n.number),r.bottom=Math.max(r.bottom,n.number),r.left=Math.min(r.left,n.min||1),r.right=Math.max(r.right,n.max||1);return r}function dt(t,e,o){const r=t.bottom-t.top+1,n=t.right-t.left+1;if(r>e.limits.maxRows||n>e.limits.maxColumns||r*n>o)throw new Error(`Excel 范围 ${M(t)} 超过导入行、列或单元格上限;请用 sheets/range 缩小范围`);return r*n}function pt(t,e){return t.top<=e.bottom&&t.bottom>=e.top&&t.left<=e.right&&t.right>=e.left}function ut(t,e){const o=[];for(const r of t.model.merges){const n=d(r);if(pt(e,n)){if(n.left<e.left||n.right>e.right||n.top<e.top||n.bottom>e.bottom)throw new Error(`${t.name}: 范围 ${M(e)} 截断合并单元格 ${r},请包含完整合并区域`);o.push(n)}}return o}function wt(t,e){const o=new Map;for(const n of e)o.set(n.top,Math.max(o.get(n.top)??n.top,n.bottom));const r=[];for(let n=t.top;n<=t.bottom;){let s=o.get(n)??n;for(let a=n;a<=s;a++)s=Math.max(s,o.get(a)??a);r.push({top:n,bottom:s}),n=s+1}return r}function yt(t,e,o,r){const n=[];let s,a=0;for(const i of t){const c=i.bottom-i.top+1;if(c>200)throw new Error("合并单元格跨越超过 200 行,无法安全分段;请先缩小或拆分该合并区域");let l=0;for(let h=i.top;h<=i.bottom;h++)l+=r(h);if(l>o&&Number.isFinite(o))throw new Error("合并区域或单行高度超过标准纸张可用高度;请使用 wide 或调整原模板行高");const f=s?i.bottom-s.top+1:c;s&&(f>e||a+l>o)&&(n.push(s),s=void 0,a=0),s?s.bottom=i.bottom:s={...i},a+=l}return s&&n.push(s),n}function Et(t){const e=new Map,o=new Set;for(const r of t){e.set(`${r.top}:${r.left}`,r);for(let n=r.top;n<=r.bottom;n++)for(let s=r.left;s<=r.right;s++)(n!==r.top||s!==r.left)&&o.add(`${n}:${s}`)}return{masters:e,covered:o}}function O(t){return JSON.parse(JSON.stringify(t))}function Mt(t,e){const o=t.template.pages.slice(e.pageStart,e.pageStart+e.pageCount),r=o[0];if(!r)throw new Error(`工作表 ${e.name} 没有可绑定页面`);const n=new Map;let s=[];for(const a of o)for(const i of a.components){if(i.kind==="list"||!i.grid||i.meta?.xlsxSheet!==e.name)continue;const c=d(String(i.meta.xlsxRange)),l=i.grid;s=l.colWidthsMm??[],l.cells.forEach((f,h)=>n.set(c.top+h,{cells:O(f),height:l.rowHeightsMm?.[h]??6}))}if(!s.length||!n.size)throw new Error(`工作表 ${e.name} 缺少导入几何元数据`);return{rows:n,widths:[...s],page:r,range:d(e.range)}}function G(t,e,o){const r=[],n=[];for(let s=e;s<=o;s++){const a=t.rows.get(s);if(!a)throw new Error(`导入模板缺少第 ${s} 行`);for(const i of a.cells)if(i&&s+(i.rowSpan??1)-1>o)throw new Error(`第 ${s} 行合并区域跨越绑定边界,请调整 header/detail 范围`);r.push(O(a.cells)),n.push(a.height)}return{cells:r,rowHeightsMm:n,colWidthsMm:t.widths,paddingMm:.25}}function xt(t,e){const o=d(t.header),r=t.detail?d(t.detail):{...e.range,top:o.bottom+1};for(const n of[o,r])if(n.left!==e.range.left||n.right!==e.range.right||n.top<e.range.top||n.bottom>e.range.bottom||n.top>n.bottom)throw new Error("绑定区域必须位于导入选区内并覆盖其完整列宽");if(r.top!==o.bottom+1)throw new Error("detail 应紧接 header,避免静态内容被隐式删除");if(t.columns.length!==e.widths.length)throw new Error("columns 应逐列映射整个选区;不能自动猜测业务字段");return bt(e,[o.top,o.bottom+1,r.bottom+1]),{header:o,detail:r}}function bt(t,e){for(const[o,r]of t.rows)for(const n of r.cells){const s=o+(n?.rowSpan??1);if(e.some(a=>o<a&&s>a))throw new Error(`第 ${o} 行合并区域跨越绑定边界,请调整 header/detail 范围`)}}function $t(t,e){const o=[];for(const r of N.resolveGridLayout(t,e.reduce((n,s)=>n+s,0),100).cells)for(let n=r.ci;n<Math.min(e.length,r.ci+(r.cell.colSpan??1));n++)o[n]=r.cell;return o}function St(t,e,o,r){if(e)return e;const n=t?.numberFormat;if(!n||n==="General")return;const s=/^(#,##)?0(?:\.(0+))?(%)?$/.exec(n);if(s){const a=s[2]?.length??0;if(a<=100)return s[3]?{kind:"percent",digits:a}:{kind:"number",digits:a,...s[1]?{thousands:!0}:{}}}r.push(`${o}: Excel 数字格式 ${n} 未自动套用到动态数据,请在 columns 中显式声明 format`)}function Rt(t,e,o,r,n){const s=$t(e,r),a=N.resolveGridLayout(o,r.reduce((f,h)=>f+h,0),20).cells;if(a.some(({cell:f})=>(f.colSpan??1)!==1||(f.rowSpan??1)!==1))throw new Error("动态明细样例行不能包含合并格;合并表头可以保留");const i=new Map(a.map(f=>[f.ci,f.cell])),c=new Set,l=t.columns.map((f,h)=>{const g=typeof f=="string"?{field:f}:f;if(!g||typeof g.field!="string"||!g.field.trim()||c.has(g.field))throw new Error(`columns[${h}] 需要唯一的非空 field`);c.add(g.field);const m=s[h]?.text??g.field,p=i.get(h),w=t.inferSampleFormats===!1?g.format:St(p,g.format,g.field,n);return{...g,...w?{format:w}:{},header:g.header??m,widthMm:r[h],style:{...p?.style,...g.style},...g.semanticRole&&!g.align?{align:"auto"}:{},...g.editable===void 0&&p?.editable===!1?{editable:!1}:{}}});return vt(t,s,l),l}function vt(t,e,o){const r=new Map;t.columns.forEach((n,s)=>{const a=e[s];if(!a||typeof n=="string")return;const i=r.get(a)??{style:{}};if(n.header!==void 0){if(i.text!==void 0&&i.text!==n.header)throw new Error("同一合并表头不能配置不同 header");i.text=n.header}kt(i.style,{...n.headerAlign?{align:n.headerAlign}:{},...n.headerStyle}),r.set(a,i)});for(const[n,s]of r)s.text!==void 0&&Object.assign(n,{text:s.text,rawText:s.text,value:s.text}),n.style={...n.style,...s.style},e.forEach((a,i)=>{a===n&&(s.text!==void 0&&(o[i].header=s.text),s.style.align!==void 0&&(o[i].headerAlign=s.style.align))})}function kt(t,e){for(const o of Object.keys(e))if(e[o]!==void 0){if(t[o]!==void 0&&t[o]!==e[o])throw new Error(`同一合并表头不能配置不同 ${o}`);Object.assign(t,{[o]:e[o]})}}function Bt(t,e){const o=t.page,r=e.rowHeightsMm.reduce((n,s)=>n+s,0);return{...o,heightMm:Math.max(o.heightMm,r+(o.marginTopMm??0)+(o.marginBottomMm??0)),components:[{kind:"rect",leftMm:o.marginLeftMm??0,topMm:o.marginTopMm??0,widthMm:t.widths.reduce((n,s)=>n+s,0),heightMm:r,grid:e}]}}function At(t,e,o,r){const n=Mt(t,e),{header:s,detail:a}=xt(o,n),i=G(n,n.range.top,s.bottom),c=G(n,a.top,a.top),l={...n.page,components:[]},f={kind:"list",id:`bound:${e.name}`,dataset:o.dataset??"detail",title:e.name,leftMm:l.marginLeftMm??0,topMm:l.marginTopMm??0,widthMm:n.widths.reduce((h,g)=>h+g,0),layout:l.layout??"page",headerGrid:i,columns:Rt(o,i,c,n.widths,r),rowHeightMm:c.rowHeightsMm[0],headerEveryPage:!0,align:"auto",paddingMm:.25,...o.rowKey?{rowKey:o.rowKey}:{},...o.revisionField?{revisionField:o.revisionField}:{},...o.sourceTokenField?{sourceTokenField:o.sourceTokenField}:{},...o.groupBy?{groupBy:o.groupBy}:{},...o.grandTotal===void 0?{}:{grandTotal:o.grandTotal}};return l.components.push(f),a.bottom===n.range.bottom?[l]:(r.push(`${e.name}: 明细区域后的静态内容保留为后续独立页面,不推断动态页脚定位`),[l,Bt(n,G(n,a.bottom+1,n.range.bottom))])}function V(t,e){const o=R.validateReportTemplate(t.template);if(!o.ok)throw new Error(`导入模板无效:${o.errors[0]?.message}`);if(!e.length)throw new Error("至少需要一个 Excel 业务绑定");const r=new Map;for(const c of e){if(!t.sheets.some(l=>l.name===c.sheet)||r.has(c.sheet))throw new Error(`绑定工作表不存在或重复:${c.sheet}`);r.set(c.sheet,c)}const n=[...t.warnings],s=t.sheets.flatMap(c=>{const l=r.get(c.name);return l?At(t,c,l,n):O(t.template.pages.slice(c.pageStart,c.pageStart+c.pageCount))}),a={...O(t.template),pages:s},i=R.validateReportTemplate(a);if(!i.ok)throw new Error(`业务模板无效:${i.errors[0]?.path} ${i.errors[0]?.message}`);return{template:a,warnings:n}}function z(t){const e=t.semanticRole??(t.type==="number"||t.type==="decimal"?"measure":t.type==="date"?"date":"text");return{field:t.field,semanticRole:e,editable:!1,...t.type==="number"&&t.digits!==void 0?{format:{kind:"number",digits:t.digits}}:{},...t.type==="date"?{format:{kind:"date",pattern:"YYYY-MM-DD"}}:{}}}function Ct(t){return t===null||typeof t=="string"||typeof t=="boolean"||typeof t=="number"&&Number.isFinite(t)}function H(t,e=0){if(Ct(t))return;if(!t||typeof t!="object"||e>16)throw new Error("绑定会话元数据只允许有限深度的普通 JSON 值");const o=Object.getPrototypeOf(t);if(Array.isArray(t)?o!==Array.prototype:o!==Object.prototype&&o!==null)throw new Error("绑定会话不能包含特殊对象原型");if(Object.getOwnPropertySymbols(t).length)throw new Error("绑定会话不能包含 Symbol");if(Array.isArray(t)&&Object.keys(t).length!==t.length)throw new Error("绑定会话数组不能包含空位或额外属性");for(const[r,n]of Object.entries(Object.getOwnPropertyDescriptors(t)))if(!(Array.isArray(t)&&r==="length")){if(["__proto__","prototype","constructor"].includes(r)||n.get||n.set||!n.enumerable)throw new Error("绑定会话包含不安全元数据");H(n.value,e+1)}}function Ot(t,e){return Tt(t,e)}function Tt(t,e){const o=t.sheets.find(c=>c.name===e.sheet);if(!o)return[];const r=d(e.regions.header),n=d(e.regions.detail),s=[r.top,r.bottom+1,n.bottom+1],a=[],i=new Set;for(const c of t.template.pages.slice(o.pageStart,o.pageStart+o.pageCount))for(const l of c.components){if(l.kind==="list"||!l.grid||l.meta?.xlsxSheet!==e.sheet)continue;const f=d(String(l.meta.xlsxRange));l.grid.cells.forEach((h,g)=>{const m=f.top+g;for(const p of h){const w=s.some(b=>m<b&&m+(p?.rowSpan??1)>b),x=m===n.top&&((p?.rowSpan??1)>1||(p?.colSpan??1)>1);if(!w&&!x)continue;const E=w?"$.recipe.regions":"$.recipe.regions.detail";i.has(E)||(i.add(E),a.push({path:E,code:"region",message:w?`第 ${m} 行合并区域跨越绑定边界,请选择完整合并区域`:"动态明细原型行不能包含合并格"}))}})}return a}function Z(t){return JSON.parse(JSON.stringify(t))}function T(t){return t instanceof Error?t.message:String(t)}function u(t,e,o,r){t.push({path:e,code:o,message:r})}function U(t,e){return{fields:t.fields,...e?{rowKey:e}:{}}}function Ft(t,e){const o=new Set;for(const[r,n]of t.entries()){const s=`$.datasets[${r}]`;if(!n||typeof n.id!="string"||!n.id.trim()||o.has(n.id)){u(e,s,"schema","数据集标识应非空且唯一");continue}o.add(n.id);try{F.validateDatasetRows([],U(n,n.rowKey));for(const[a,i]of n.fields.entries())i.digits!==void 0&&(!Number.isInteger(i.digits)||i.digits<0||i.digits>100)&&u(e,`${s}.fields[${a}].digits`,"schema","显示精度应为 0–100 的整数")}catch(a){u(e,s,"schema",T(a))}}}function Nt(t,e,o){const r=t.sheets.find(i=>i.name===e.sheet);if(!r){u(o,"$.recipe.sheet","source","指定的工作表不存在");return}let n;try{n=d(r.range)}catch(i){u(o,"$.source.sheets","source",T(i));return}const s=new Map;for(const i of["title","header","detail","footer"]){const c=e.regions?.[i];if(!(!c&&(i==="title"||i==="footer")))try{const l=d(c??"");if(l.left!==n.left||l.right!==n.right||l.top<n.top||l.bottom>n.bottom)throw new Error("区域必须覆盖选区完整列宽,并位于原始工作表内");s.set(i,l)}catch(l){u(o,`$.recipe.regions.${i}`,"region",T(l))}}const a=[...s.values()];a.length&&(a[0].top!==n.top||a[a.length-1].bottom!==n.bottom)&&u(o,"$.recipe.regions","region","标题、表头、明细、页脚应完整覆盖来源,不能隐式删除静态内容");for(let i=1;i<a.length;i++)a[i].top!==a[i-1].bottom+1&&u(o,"$.recipe.regions","region","各区域应顺序相邻且不重叠")}function It(t,e,o,r){if(!Array.isArray(t.fields)||t.fields.length!==o)return u(r,"$.recipe.fields","mapping","每个物理 Excel 列必须显式绑定一个业务字段"),0;const n=new Set(e.fields.map(i=>i.field)),s=new Set;let a=0;t.fields.forEach((i,c)=>{typeof i!="string"||!n.has(i)?u(r,`$.recipe.fields[${c}]`,"mapping","请选择契约中已声明的字段"):s.has(i)?u(r,`$.recipe.fields[${c}]`,"mapping","同一业务字段不能重复绑定物理列"):(a++,s.add(i))});try{if(!t.rowKey)throw new Error("请明确选择稳定业务主键,不能使用展示行号");const i=U(e,t.rowKey),c=F.validateDatasetRows(e.samples??[],i,{path:`$.datasets.${e.id}.samples`,maxRows:100,maxCells:2e5,maxIssues:30});for(const l of c.issues)u(r,l.path,l.code==="row-key"?"row-key":"schema",l.message)}catch(i){u(r,"$.recipe.rowKey","row-key",T(i))}return a}function Q(t,e){const o=[];return!e||e.version!=="1.0"?[{path:"$.recipe.version",code:"schema",message:"不支持的 Excel 绑定配置版本"}]:(Nt(t,e,o),o.length||o.push(...Ot(t,e)),o)}function X(t,e,o){const r=[];if(!e||e.version!=="1.0")return{ok:!1,issues:[{path:"$.recipe.version",code:"schema",message:"不支持的 Excel 绑定配置版本"}],mapped:0,total:0};Ft(o,r);const n=t.sheets.find(i=>i.name===e.sheet)?.columnCount??0,s=o.find(i=>i.id===e.dataset);let a=0;return s?r.some(i=>i.code==="schema")||(a=It(e,s,n,r)):u(r,"$.recipe.dataset","schema","请明确选择宿主提供的数据集契约"),{ok:r.length===0,issues:r,mapped:a,total:n}}function tt(t,e,o){const r=X(t,e,o);if(!e||e.version!=="1.0")return r;const n=[...Q(t,e),...r.issues];return{...r,ok:n.length===0,issues:n}}function Kt(t,e,o,r){const n=tt(t,e,o);if(!n.ok)throw new Error(n.issues.map(f=>`${f.path}: ${f.message}`).join(`
2
+ `));const s=t.sheets.find(f=>f.name===e.sheet),a={...t,sheets:[{...s,pageStart:0}],template:{...t.template,pages:t.template.pages.slice(s.pageStart,s.pageStart+s.pageCount)}},i=new Map(o.find(f=>f.id===e.dataset).fields.map(f=>[f.field,f])),c={sheet:e.sheet,dataset:e.dataset,header:e.regions.header,detail:e.regions.detail,rowKey:e.rowKey,inferSampleFormats:!1,columns:e.fields.map(f=>z(i.get(f)))},l=V(a,[c]);return{document:R.defineReportTemplate({...r,template:l.template}),recipe:Z(e),warnings:l.warnings}}function Gt(t,e){if(t?.version!=="1.0"||!Array.isArray(t.fields)||t.fields.length>16384||t.fields.some(o=>typeof o!="string"))throw new Error("Excel 绑定配置无效");if(typeof t.dataset!="string"||typeof t.rowKey!="string"||!t.regions||typeof e?.id!="string"||typeof e.name!="string")throw new Error("Excel 绑定参数或标识无效");for(const o of Object.values(t.regions))o!==""&&d(o)}function jt(t){for(const e of t.sheets)if(d(e.range),typeof e.name!="string"||![e.index,e.rowCount,e.columnCount,e.pageCount].every(o=>Number.isInteger(o)&&o>0)||!Number.isInteger(e.pageStart)||e.pageStart<0||e.pageStart+e.pageCount>t.template.pages.length)throw new Error("Excel 绑定工作表几何元数据无效")}function Ht(t,e,o){if(H({sheets:t.sheets,warnings:t.warnings,recipe:e,identity:o}),!Array.isArray(t.sheets)||!t.sheets.length||t.sheets.length>32||!Array.isArray(t.warnings)||t.warnings.some(r=>typeof r!="string"))throw new Error("Excel 绑定来源元数据无效");if(Gt(e,o),!t.sheets.some(r=>r.name===e.sheet))throw new Error("Excel 绑定工作表不存在");jt(t)}function et(t,e,o){return Ht(t,e,o),R.parseReportTemplate({schemaVersion:"1.0",id:o.id,name:o.name,template:t.template}),Z({version:"1.0",source:t,recipe:e,identity:o})}function Dt(t){if(typeof t=="string"&&t.length>1e7)throw new Error("Excel 绑定会话超过 1000 万字符上限");const e=typeof t=="string"?JSON.parse(t):t;if(!e||e.version!=="1.0"||e.recipe?.version!=="1.0"||!Array.isArray(e.source?.sheets))throw new Error("Excel 绑定会话结构或版本无效");return et(e.source,e.recipe,e.identity)}function Lt(t,e,o,r){const n=t.sheets.find(c=>c.name===e);if(!n)throw new Error("工作表不存在");const s=d(n.range),a=Math.min(o,r),i=Math.max(o,r);if(!Number.isInteger(a)||!Number.isInteger(i)||a<s.top||i>s.bottom)throw new Error("选中行超出来源区域");return M({...s,top:a,bottom:i})}function P(t,e,o){const r=t??e;if(!Number.isInteger(r)||r<1||r>o)throw new Error(`预览窗口大小应为 1–${o} 的整数`);return r}function Y(t,e,o){const r=t??e;if(!Number.isInteger(r))throw new Error("预览起点应为整数");return Math.max(e,Math.min(o,r))}function Jt(t,e,o={}){const r=t.sheets.find(g=>g.name===e);if(!r)throw new Error("指定的工作表不存在");const n=d(r.range),s=Y(o.row,n.top,n.bottom),a=Y(o.column,n.left,n.right),i=Math.min(n.bottom,s+P(o.rows,24,100)-1),c=Math.min(n.right,a+P(o.columns,12,32)-1),l=Array.from({length:i-s+1},(g,m)=>({row:s+m,cells:[]})),f=new Set;for(const g of t.template.pages.slice(r.pageStart,r.pageStart+r.pageCount))for(const m of g.components){if(m.kind==="list"||!m.grid||m.meta?.xlsxSheet!==e)continue;const p=d(String(m.meta.xlsxRange));if(p.bottom<s||p.top>i)continue;const w=N.resolveGridLayout(m.grid,m.widthMm,m.heightMm);for(const x of w.cells)h(x.cell,p.top+x.ri,p.left+x.ci)}for(const g of l){for(let m=a;m<=c;m++)f.has(`${g.row}:${m}`)||g.cells.push({address:`${S(m)}${g.row}`,row:g.row,column:m,text:"",rowSpan:1,colSpan:1,continued:!1});g.cells.sort((m,p)=>m.column-p.column)}return{top:s,bottom:i,left:a,right:c,source:n,rows:l,columns:Array.from({length:c-a+1},(g,m)=>({column:a+m,name:S(a+m)}))};function h(g,m,p){const w=m+(g.rowSpan??1)-1,x=p+(g.colSpan??1)-1;if(w<s||m>i||x<a||p>c)return;const E=Math.max(s,m),b=Math.max(a,p),J=Math.min(i,w)-E+1,W=Math.min(c,x)-b+1;l[E-s].cells.push({address:`${S(p)}${m}`,row:E,column:b,text:g.text??g.rawText??String(g.value??""),rowSpan:J,colSpan:W,continued:E!==m||b!==p,style:g.style});for(let I=E;I<E+J;I++)for(let K=b;K<b+W;K++)f.add(`${I}:${K}`)}}function v(t){return JSON.parse(JSON.stringify(t))}function ot(t,e){const o=t.sheets.find(i=>i.name===e);if(!o)throw new Error("指定的工作表不存在");const r=t.template.pages.slice(o.pageStart,o.pageStart+o.pageCount),n=r[0];if(!n)throw new Error("工作表没有可绑定的页面");const s={page:n,range:d(o.range),widths:[],heights:new Map,cells:[],cellsByRow:new Map,topOffsets:new Map};for(const i of r)for(const c of i.components){if(c.kind==="list"||!c.grid||c.meta?.xlsxSheet!==e)continue;const l=d(String(c.meta.xlsxRange));s.widths.length||(s.widths=[...c.grid.colWidthsMm??[]]),c.grid.cells.forEach((f,h)=>s.heights.set(l.top+h,c.grid.rowHeightsMm?.[h]??6));for(const f of N.resolveGridLayout(c.grid,c.widthMm,c.heightMm).cells){const h=l.top+f.ri,g=l.left+f.ci;s.cells.push({top:h,left:g,bottom:h+(f.cell.rowSpan??1)-1,right:g+(f.cell.colSpan??1)-1,cell:f.cell})}}if(s.widths.length!==s.range.right-s.range.left+1||s.heights.size!==s.range.bottom-s.range.top+1)throw new Error("来源工作表几何元数据不完整");let a=0;for(let i=s.range.top;i<=s.range.bottom;i++)s.topOffsets.set(i,a),a+=s.heights.get(i);s.topOffsets.set(s.range.bottom+1,a);for(const i of s.cells)for(let c=i.top;c<=i.bottom;c++){const l=s.cellsByRow.get(c)??[];l.push(i),s.cellsByRow.set(c,l)}return s}function rt(t,e){return t.left<=e.right&&e.left<=t.right&&t.top<=e.bottom&&e.top<=t.bottom}function k(t,e){return t.top<=e.top&&t.bottom>=e.bottom&&t.left<=e.left&&t.right>=e.right}function nt(t,e){return t.widths.slice(e.left-t.range.left,e.right-t.range.left+1).reduce((o,r)=>o+r,0)}function C(t,e){return(t.topOffsets.get(e.bottom+1)??0)-(t.topOffsets.get(e.top)??0)}function A(t,e){const o=new Set;for(let r=e.top;r<=e.bottom;r++)for(const n of t.cellsByRow.get(r)??[])rt(n,e)&&o.add(n);return[...o]}function st(t,e){for(const o of A(t,e))if(!k(e,o))throw new Error(`合并区域 ${M(o)} 跨越选区 ${M(e)}`)}function j(t,e,o=[]){const r=A(t,e);for(const i of r)if(!k(e,i))throw new Error(`合并区域 ${M(i)} 跨越选区 ${M(e)}`);const n=[],s=new Map,a=new Set;for(const i of r)if(!o.some(c=>k(c,i))){s.set(`${i.top}:${i.left}`,i);for(let c=i.top;c<=i.bottom;c++)for(let l=i.left;l<=i.right;l++)a.add(`${c}:${l}`)}for(let i=e.top;i<=e.bottom;i++){const c=[];for(let l=e.left;l<=e.right;l++){const f=s.get(`${i}:${l}`);f?(c.push(v(f.cell)),l=f.right):a.has(`${i}:${l}`)||c.push(null)}n.push(c)}return{cells:n,colWidthsMm:t.widths.slice(e.left-t.range.left,e.right-t.range.left+1),rowHeightsMm:Array.from({length:e.bottom-e.top+1},(i,c)=>t.heights.get(e.top+c)),paddingMm:.25}}function B(t){const e=d(t.range);return t.headerRange?{...e,top:d(t.headerRange).top}:e}function D(t,e){return(t.page.marginTopMm??0)+(t.topOffsets.get(e)??0)}function it(t,e){return{xlsxFlow:{version:"1.0",columnStart:e.left-t.range.left}}}function at(t,e,o,r,n=[]){const s=j(t,o,n);for(const a of s.cells)for(const i of a)i&&(i.editable=!1,delete i.source);return{kind:"rect",nid:r,leftMm:t.page.marginLeftMm??0,topMm:D(t,o.top),widthMm:nt(t,o),heightMm:C(t,o),grid:s,meta:it(t,o)}}function Wt(t,e,o,r){const n=d(o.range),s=B(o),a=j(t,n),i=new Map(r.fields.map(f=>[f.field,f])),c=a.colWidthsMm,l=o.fields.map((f,h)=>({...z(i.get(f)),header:i.get(f).label??f,widthMm:c[h],style:v(a.cells[0]?.[h]?.style??{}),align:"auto"}));return{kind:"list",id:`xlsx-region:${o.id}`,dataset:o.dataset,rowKey:o.rowKey,...o.revisionField?{revisionField:o.revisionField}:{},...o.sourceTokenField?{sourceTokenField:o.sourceTokenField}:{},title:`${e.sheet} · ${o.id}`,layout:t.page.layout??"wide",leftMm:(t.page.marginLeftMm??0)+t.widths.slice(0,n.left-t.range.left).reduce((f,h)=>f+h,0),topMm:D(t,s.top),widthMm:nt(t,n),rowHeightMm:a.rowHeightsMm[0],header:!!o.headerRange,headerEveryPage:o.mode==="repeat",...o.mode==="record"?{cardinality:"record"}:{},...o.headerRange?{headerGrid:j(t,d(o.headerRange))}:{},columns:l,paddingMm:a.paddingMm,meta:it(t,n)}}function q(t,e,o,r=0){const n=[],s=t.page.heightMm-(t.page.marginTopMm??0)-(t.page.marginBottomMm??0)-r,a=Math.max(1,Math.min(100,Math.floor(1e4/t.widths.length)));for(let i=e;i<=o;){const c=i;let l=i,f=0;for(;i<=o;){let h=i;for(let m=i;m<=h;m++)for(const p of t.cellsByRow.get(m)??[])h=Math.max(h,p.bottom);if(h>o)throw new Error("静态合并区域跨越动态绑定边界,请调整区域");const g=C(t,{...t.range,top:i,bottom:h});if(i>c&&(h-c+1>a||f+g>s))break;if(g>s)throw new Error("静态合并区域高度超过单页可用高度,请调整原始模板");f+=g,l=h,i=h+1}n.push({range:{...t.range,top:c,bottom:l},bindings:[]})}return n}function _t(t,e){const o=[...e.regions].sort((i,c)=>B(i).top-B(c).top),r=[];let n=t.range.top;const s=e.footerRange?C(t,d(e.footerRange)):0;for(const i of o){const c=B(i),l=r[r.length-1];if(l?.bindings.length&&l.range.top===c.top&&l.range.bottom===c.bottom){l.bindings.push(i);continue}n<c.top&&r.push(...q(t,n,c.top-1,s)),r.push({range:{...t.range,top:c.top,bottom:c.bottom},bindings:[i]}),n=c.bottom+1}const a=e.footerRange?d(e.footerRange).top-1:t.range.bottom;return n<=a&&r.push(...q(t,n,a,s)),r}function Pt(t,e,o,r,n){const s=[],a=o.bindings.map(B),i=o.bindings.some(l=>l.mode==="repeat"),c=A(t,o.range).some(l=>!a.some(f=>k(f,l)));!i&&(!o.bindings.length||c)&&s.push(at(t,e,o.range,`xlsx-static:${r}`,a));for(const l of o.bindings)s.push(Wt(t,e,l,n.find(f=>f.id===l.dataset)));return{components:s,flow:{componentIds:s.map(l=>l.kind==="list"?l.id:l.nid),topMm:D(t,o.range.top),heightMm:C(t,o.range)}}}function Yt(t,e,o,r){const n=ot(t,e.sheet),s={...v(n.page),components:[]},a=_t(n,e).map((i,c)=>Pt(n,e,i,c,o));if(s.components=a.flatMap(i=>i.components),s.flow={bands:a.map(i=>i.flow)},s.meta={xlsxFlow:{version:"1.0",templateId:r,sheet:e.sheet,fullWidthsMm:n.widths}},e.footerRange){const i=d(e.footerRange),c=at(n,e,i,"xlsx-footer");c.pageAnchor="footer",c.topMm=s.heightMm-(s.marginBottomMm??0)-c.heightMm,s.components.push(c)}return{...v(t.template),pages:[s]}}function $(t){return t instanceof Error?t.message:String(t)}function y(t,e,o,r){t.push({path:e,code:o,message:r})}function L(t,e,o=!1){const r=d(t);if(!k(e.range,r))throw new Error("绑定范围应完整位于来源工作表内");if(o&&r.top!==r.bottom)throw new Error("每个动态区域应选择一行原型;多个数据行由 repeat 自动扩展");return st(e,r),r}function qt(t){const e=t.cell;return!!e.formula||!!e.children?.length||e.value!==null&&e.value!==void 0&&e.value!==""||!!e.text||!!e.rawText}function Vt(t,e,o){if(!t.headerRange)return;const r=L(t.headerRange,e);if(r.left!==o.left||r.right!==o.right||r.bottom+1!==o.top)throw new Error("区域表头应与原型等列宽,并紧接原型上方");return r}function zt(t,e){const o=L(t.range,e,!0),r=Vt(t,e,o);if(st(e,{...e.range,top:r?.top??o.top,bottom:o.bottom}),A(e,o).some(s=>s.bottom!==s.top||s.left!==s.right))throw new Error("动态原型行不能包含合并格;请保留合并表头并选择其下方数据行");if(t.mode==="repeat"){const s={...e.range,top:r?.top??o.top,bottom:o.bottom};if(A(e,s).some(a=>!k({...o,top:s.top},a)&&qt(a)))throw new Error("纵向重复区域的旁列存在静态内容,无法安全拉伸;请扩大区域或将静态内容移至独立行")}return{...o,top:r?.top??o.top}}function lt(t){if(!t||t.version!=="2.0"||typeof t.sheet!="string"||!Array.isArray(t.regions)||!t.regions.length||t.regions.length>128)throw new Error("多区域绑定应为 version 2.0,并包含 1–128 个区域")}function ct(t,e){const o=[];try{lt(e)}catch(a){return[{path:"$.recipe",code:"schema",message:$(a)}]}let r;try{r=ot(t,e.sheet)}catch(a){return[{path:"$.recipe.sheet",code:"source",message:$(a)}]}const n=new Set,s=[];if(e.regions.forEach((a,i)=>{const c=`$.recipe.regions[${i}]`;try{if(!a||typeof a.id!="string"||!a.id.trim()||n.has(a.id))throw new Error("区域标识应非空且唯一");if(n.add(a.id),!["record","repeat"].includes(a.mode))throw new Error("区域模式应为 record 或 repeat");const l=zt(a,r);for(const f of s){if(rt(l,f.range))throw new Error(`区域与 ${f.path} 重叠(含表头)`);if(l.top<=f.range.bottom&&f.range.top<=l.bottom&&(a.mode==="repeat"||f.mode==="repeat"))throw new Error("同一行不能并排放置重复区域;请按纵向顺序排列");if(l.top<=f.range.bottom&&f.range.top<=l.bottom&&(l.top!==f.range.top||l.bottom!==f.range.bottom))throw new Error("并排单记录区域应使用相同的起止行(包括表头),避免不明确的位移")}s.push({range:l,mode:a.mode,path:c})}catch(l){y(o,c,"region",$(l))}}),e.footerRange)try{const a=L(e.footerRange,r);if(a.left!==r.range.left||a.right!==r.range.right||a.bottom!==r.range.bottom)throw new Error("重复页尾应覆盖完整列宽并位于来源最后几行");if(s.some(i=>i.range.bottom>=a.top))throw new Error("页尾与动态区域或区域表头相交");if(C(r,a)>=r.page.heightMm-(r.page.marginTopMm??0)-(r.page.marginBottomMm??0))throw new Error("页尾高度占满单页,不能为报表明细预留空间")}catch(a){y(o,"$.recipe.footerRange","region",$(a))}return o}function Zt(t,e){const o=new Map;for(const[r,n]of t.entries())try{if(!n||typeof n.id!="string"||!n.id.trim()||o.has(n.id))throw new Error("数据集标识应非空且唯一");F.validateDatasetRows([],{fields:n.fields,...n.rowKey?{rowKey:n.rowKey}:{}});for(const s of n.fields)if(s.digits!==void 0&&(!Number.isInteger(s.digits)||s.digits<0||s.digits>100))throw new Error("显示精度应为 0–100 的整数");o.set(n.id,n)}catch(s){y(e,`$.datasets[${r}]`,"schema",$(s))}return o}function Ut(t,e,o,r){const n=d(t.range),s=n.right-n.left+1;if(!Array.isArray(t.fields)||t.fields.length!==s)return y(r,`${o}.fields`,"mapping","区域每个物理列应显式绑定一个字段"),0;const a=new Set(e.fields.map(l=>l.field)),i=new Set;let c=0;if(t.fields.forEach((l,f)=>{!a.has(l)||i.has(l)?y(r,`${o}.fields[${f}]`,"mapping","请选择契约内已声明且不重复的字段"):(i.add(l),c++)}),!t.rowKey)y(r,`${o}.rowKey`,"row-key","每个区域应声明稳定业务主键");else{const l=F.validateDatasetRows(e.samples??[],{fields:e.fields,rowKey:t.rowKey},{path:`$.datasets.${e.id}.samples`,maxRows:100,maxIssues:30});for(const f of l.issues)y(r,f.path,f.code==="row-key"?"row-key":"schema",f.message)}for(const l of["revisionField","sourceTokenField"])t[l]!==void 0&&!a.has(t[l])&&y(r,`${o}.${l}`,"source","并发字段应引用同一区域数据集契约内的字段");return t.mode==="record"&&(e.samples?.length??0)>1&&y(r,o,"schema","record 区域数据集最多一行;多行请使用 repeat"),c}function ft(t,e){const o=[];try{lt(t)}catch(a){return{ok:!1,issues:[{path:"$.recipe",code:"schema",message:$(a)}],mapped:0,total:0}}const r=Zt(e,o);let n=0,s=0;for(const[a,i]of t.regions.entries()){const c=`$.recipe.regions[${a}]`;try{const l=d(i.range);s+=l.right-l.left+1;const f=r.get(i.dataset);f?n+=Ut(i,f,c,o):y(o,`${c}.dataset`,"source","请选择宿主提供的数据集契约")}catch(l){y(o,c,"schema",$(l))}}return{ok:o.length===0,issues:o,mapped:n,total:s}}function gt(t,e,o){const r=ft(e,o),n=[...ct(t,e),...r.issues];return{...r,ok:!n.length,issues:n}}function Qt(t,e,o,r){const n=gt(t,e,o);if(!n.ok)throw new Error(n.issues.map(s=>`${s.path}: ${s.message}`).join(`
3
+ `));return{document:R.defineReportTemplate({...r,template:Yt(t,e,o,r.id)}),recipe:v(e),warnings:[...t.warnings]}}function Xt(t){if(!t||t.version!=="2.0"||typeof t.sheet!="string"||!Array.isArray(t.regions)||!t.regions.length||t.regions.length>128)throw new Error("多区域绑定会话配置或版本无效");for(const e of t.regions){if(!e||typeof e.id!="string"||typeof e.dataset!="string"||typeof e.rowKey!="string"||!["record","repeat"].includes(e.mode)||!Array.isArray(e.fields)||e.fields.length>2048||e.fields.some(o=>typeof o!="string"))throw new Error("多区域绑定会话的区域结构无效");e.range&&d(e.range),e.headerRange&&d(e.headerRange)}t.footerRange&&d(t.footerRange)}function ht(t,e,o){if(H({sheets:t.sheets,warnings:t.warnings,recipe:e,identity:o}),Xt(e),!Array.isArray(t.sheets)||!t.sheets.length||!Array.isArray(t.warnings)||t.warnings.some(r=>typeof r!="string")||!t.sheets.some(r=>r.name===e.sheet))throw new Error("多区域绑定会话的来源无效");for(const r of t.sheets)if(d(r.range),![r.index,r.rowCount,r.columnCount,r.pageCount].every(n=>Number.isInteger(n)&&n>0)||!Number.isInteger(r.pageStart)||r.pageStart<0||r.pageStart+r.pageCount>t.template.pages.length)throw new Error("多区域绑定会话的工作表几何无效");return R.parseReportTemplate({schemaVersion:"1.0",...o,template:t.template}),v({version:"2.0",source:t,recipe:e,identity:o})}function te(t){if(typeof t=="string"&&t.length>1e7)throw new Error("绑定会话超过 1000 万字符上限");const e=typeof t=="string"?JSON.parse(t):t;if(!e||e.version!=="2.0"||!e.source||!e.recipe||!e.identity)throw new Error("多区域绑定会话结构或版本无效");return ht(e.source,e.recipe,e.identity)}function ee(t,e,o,r=o){const n=t.sheets.find(i=>i.name===e);if(!n)throw new Error("工作表不存在");const s=d(n.range);if(![o.row,o.column,r.row,r.column].every(Number.isInteger))throw new Error("单元格坐标应为整数");const a={top:Math.min(o.row,r.row),bottom:Math.max(o.row,r.row),left:Math.min(o.column,r.column),right:Math.max(o.column,r.column)};if(a.top<s.top||a.bottom>s.bottom||a.left<s.left||a.right>s.right)throw new Error("选区超出来源工作表");return M(a)}exports.bindExcelTemplate=V;exports.checkedRange=dt;exports.columnName=S;exports.createExcelBindingDocument=Kt;exports.createExcelBindingSession=et;exports.createExcelRegionBindingDocument=Qt;exports.createExcelRegionBindingSession=ht;exports.excelBindingCellRange=ee;exports.excelBindingRowRange=Lt;exports.getExcelSheetWindow=Jt;exports.mergeLookup=Et;exports.mergeRowGroups=wt;exports.parseExcelBindingSession=Dt;exports.parseExcelRegionBindingSession=te;exports.parseImportRange=d;exports.rangeName=M;exports.rowSegments=yt;exports.selectedMerges=ut;exports.selectedRange=mt;exports.validateExcelBindingFields=X;exports.validateExcelBindingRecipe=tt;exports.validateExcelBindingRegions=Q;exports.validateExcelRegionBindings=gt;exports.validateExcelRegionFields=ft;exports.validateExcelRegionGeometry=ct;
@@ -1,4 +1,4 @@
1
- import { v as f, R as l } from "./param-validation-BWNjLcN0.js";
1
+ import { v as f, R as l } from "./param-validation-BlHHXs6u.js";
2
2
  function m(e, s) {
3
3
  const a = /* @__PURE__ */ new Set();
4
4
  return s.flatMap((r) => {
@@ -1 +1 @@
1
- "use strict";const s=require("./param-validation-CiTxFeZ8.cjs");function l(e,f){const a=new Set;return f.flatMap(r=>{const t=Object.prototype.hasOwnProperty.call(e,r)?e[r]:void 0,n=t?.params??(typeof t?.template=="function"?[]:t?.template.params)??[],i=s.validateReportParamDefinitions(n);if(i.length)throw new s.ReportParamValidationError(i);return n.filter(o=>a.has(o.field)?!1:(a.add(o.field),!0))})}exports.getReportParamDefs=l;
1
+ "use strict";const s=require("./param-validation-DCK039V1.cjs");function l(e,f){const a=new Set;return f.flatMap(r=>{const t=Object.prototype.hasOwnProperty.call(e,r)?e[r]:void 0,n=t?.params??(typeof t?.template=="function"?[]:t?.template.params)??[],i=s.validateReportParamDefinitions(n);if(i.length)throw new s.ReportParamValidationError(i);return n.filter(o=>a.has(o.field)?!1:(a.add(o.field),!0))})}exports.getReportParamDefs=l;
@@ -47,6 +47,8 @@ declare interface GridCell {
47
47
  value?: string | number | boolean | null;
48
48
  /** Excel 数字格式(例如 #,##0.00 / 0.00%),不改变 text。 */
49
49
  numberFormat?: string;
50
+ /** Physical left inset for hierarchical labels; raw value stays unchanged. */
51
+ indentMm?: number;
50
52
  /** 编辑输入类型;省略时只按原始值推断,数字字符串不会被转换为数值。 */
51
53
  valueType?: "text" | "number" | "boolean";
52
54
  /** 单元格级编辑控制;预览仍需显式开启 editing。 */
@@ -107,6 +109,7 @@ declare interface PlanGrid {
107
109
  }
108
110
 
109
111
  declare interface PlanPage {
112
+ meta?: Record<string, unknown>;
110
113
  /** wide 表示完整自然列宽;页面仅为预览的垂直窗口分段。 */
111
114
  layout?: "page" | "wide";
112
115
  pageWidthMm: number;
@@ -271,7 +274,7 @@ declare interface ReportParamDef {
271
274
  field: string;
272
275
  /** 显示名(缺省用 field) */
273
276
  label?: string;
274
- type?: "text" | "number" | "date" | "select";
277
+ type?: "text" | "number" | "date" | "month" | "year" | "dateRange" | "select";
275
278
  /** select 选项 */
276
279
  options?: Array<{
277
280
  label: string;
@@ -280,7 +283,7 @@ declare interface ReportParamDef {
280
283
  defaultValue?: string;
281
284
  required?: boolean;
282
285
  placeholder?: string;
283
- /** 数字上下界;date 参数使用 YYYY-MM-DD 字符串(含边界)。 */
286
+ /** 数字上下界;日期/月/年使用对应规范字符串;dateRange 对两端使用 YYYY-MM-DD 边界(含边界)。 */
284
287
  min?: number | string;
285
288
  max?: number | string;
286
289
  minLength?: number;
@@ -47,6 +47,8 @@ declare interface GridCell {
47
47
  value?: string | number | boolean | null;
48
48
  /** Excel 数字格式(例如 #,##0.00 / 0.00%),不改变 text。 */
49
49
  numberFormat?: string;
50
+ /** Physical left inset for hierarchical labels; raw value stays unchanged. */
51
+ indentMm?: number;
50
52
  /** 编辑输入类型;省略时只按原始值推断,数字字符串不会被转换为数值。 */
51
53
  valueType?: "text" | "number" | "boolean";
52
54
  /** 单元格级编辑控制;预览仍需显式开启 editing。 */
@@ -107,6 +109,7 @@ declare interface PlanGrid {
107
109
  }
108
110
 
109
111
  declare interface PlanPage {
112
+ meta?: Record<string, unknown>;
110
113
  /** wide 表示完整自然列宽;页面仅为预览的垂直窗口分段。 */
111
114
  layout?: "page" | "wide";
112
115
  pageWidthMm: number;
@@ -271,7 +274,7 @@ declare interface ReportParamDef {
271
274
  field: string;
272
275
  /** 显示名(缺省用 field) */
273
276
  label?: string;
274
- type?: "text" | "number" | "date" | "select";
277
+ type?: "text" | "number" | "date" | "month" | "year" | "dateRange" | "select";
275
278
  /** select 选项 */
276
279
  options?: Array<{
277
280
  label: string;
@@ -280,7 +283,7 @@ declare interface ReportParamDef {
280
283
  defaultValue?: string;
281
284
  required?: boolean;
282
285
  placeholder?: string;
283
- /** 数字上下界;date 参数使用 YYYY-MM-DD 字符串(含边界)。 */
286
+ /** 数字上下界;日期/月/年使用对应规范字符串;dateRange 对两端使用 YYYY-MM-DD 边界(含边界)。 */
284
287
  min?: number | string;
285
288
  max?: number | string;
286
289
  minLength?: number;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("node:worker_threads"),j=require("node:crypto"),l=require("node:fs"),R=require("node:path");function C(e,t,r){if(!r?.aborted)try{const o=e?.({...t});o&&typeof o.then=="function"&&Promise.resolve(o).catch(()=>{})}catch{}}function H(e,t,r){e.editable!==void 0&&typeof e.editable!="boolean"&&r.push({path:`${t}.editable`,message:"编辑控制应为布尔值"}),e.valueType!==void 0&&!["text","number","boolean"].includes(e.valueType)&&r.push({path:`${t}.valueType`,message:"编辑类型应为 text、number 或 boolean"})}function K(e,t,r){H(e,t,r),e.derived!==void 0&&typeof e.derived!="boolean"&&r.push({path:`${t}.derived`,message:"派生结果标记应为布尔值"}),D(e.source,`${t}.source`,r,!0),e.formula!==void 0&&typeof e.formula!="string"&&r.push({path:`${t}.formula`,message:"单元格公式应为字符串"})}function D(e,t,r,o=!1){if(e===void 0)return;if(!e||typeof e!="object"||Array.isArray(e)){r.push({path:t,message:"业务来源应为对象"});return}const n=e;for(const s of["datasetId",...o?["field"]:[]])(typeof n[s]!="string"||!n[s].trim())&&r.push({path:`${t}.${s}`,message:"业务标识应为非空字符串"});for(const s of["rowKey","revision"]){const i=n[s];i===void 0&&!(o&&s==="rowKey")||typeof i!="string"&&!(typeof i=="number"&&Number.isFinite(i))&&r.push({path:`${t}.${s}`,message:"业务键及修订号应为字符串或有限数字"})}n.sourceToken!==void 0&&typeof n.sourceToken!="string"&&r.push({path:`${t}.sourceToken`,message:"来源令牌应为字符串"})}const V=new Set(["text","image","barcode","qrcode","chart","line","rect","ellipse"]);function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function G(e,t,r,o){const n=e[t];(typeof n!="number"||!Number.isFinite(n))&&o.push({path:`${r}.${t}`,message:`应为有限数字,实际 ${JSON.stringify(n)}`})}function X(e,t,r){if(e!==void 0){const o=`${t}.table`;if(!S(e))r.push({path:o,message:"逻辑表来源应为对象"});else{D(e.source,`${o}.source`,r),(typeof e.id!="string"||!e.id.trim())&&r.push({path:`${o}.id`,message:"逻辑表 ID 应为非空字符串"});const n=e.role;["header","body","group-header","subtotal","grand-total"].includes(n)||r.push({path:`${o}.role`,message:"未知逻辑表行角色"});const s=e.rowIndex;(typeof s!="number"||!Number.isInteger(s)||(n==="header"?s!==-1:s<0))&&r.push({path:`${o}.rowIndex`,message:"表头索引应为 -1,内容行索引应为非负整数"}),(!Array.isArray(e.columnKeys)||e.columnKeys.some(i=>typeof i!="string"))&&r.push({path:`${o}.columnKeys`,message:"逻辑列字段应为字符串数组"}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${o}.layout`,message:"布局应为 page 或 wide"}),e.title!==void 0&&typeof e.title!="string"&&r.push({path:`${o}.title`,message:"逻辑表名称应为字符串"})}}}function Z(e,t,r,o){if(e!==void 0)if(!S(e)||!Array.isArray(e.cells))r.push({path:`${t}.grid.cells`,message:"grid.cells 应为二维数组"});else{const n=e.paddingMm;n!==void 0&&(typeof n!="number"||!Number.isFinite(n)||n<0)&&r.push({path:`${t}.grid.paddingMm`,message:"单元格内距应为有限非负数"}),e.cells.forEach((s,i)=>{if(!Array.isArray(s)){r.push({path:`${t}.grid.cells.${i}`,message:"行应为数组"});return}s.forEach((m,h)=>{if(m==null)return;const u=`${t}.grid.cells.${i}.${h}`;if(!S(m)){r.push({path:u,message:"网格单元格应为对象或 null"});return}K(m,u,r),Array.isArray(m.children)&&m.children.forEach((b,x)=>{F(b,`${t}.grid.cells.${i}.${h}.children.${x}`,r,o)})})})}}function Q(e,t,r){e!==void 0&&(Array.isArray(e)?e.forEach((o,n)=>{(!S(o)||!Array.isArray(o.segments))&&r.push({path:`${t}.richParagraphs.${n}`,message:"段落缺少 segments 数组"})}):r.push({path:`${t}.richParagraphs`,message:"richParagraphs 应为数组"}))}function F(e,t,r,o=[]){if(!S(e)){r.push({path:t,message:"组件应为对象"});return}const n=e.kind;typeof n!="string"?r.push({path:`${t}.kind`,message:"组件缺少 kind 字符串"}):V.has(n)||o.push({path:`${t}.kind`,message:`未知组件类型 ${JSON.stringify(n)},将以兜底方式渲染`});for(const s of["leftMm","topMm","widthMm","heightMm"])G(e,s,t,r);typeof e.leftMm=="number"&&e.leftMm<-100&&r.push({path:`${t}.leftMm`,message:"几何数值异常(leftMm<-100)"});for(const s of["widthMm","heightMm"])typeof e[s]=="number"&&e[s]<0&&r.push({path:`${t}.${s}`,message:"组件尺寸不能为负数"});X(e.table,t,r),e.pageAnchor!==void 0&&!["header","footer"].includes(e.pageAnchor)&&r.push({path:`${t}.pageAnchor`,message:"页面锚点应为 header 或 footer"}),e.lineDirection!==void 0&&!["down","up"].includes(e.lineDirection)&&r.push({path:`${t}.lineDirection`,message:"线段方向应为 down 或 up"}),Z(e.grid,t,r,o),Q(e.richParagraphs,t,r)}function Y(e,t,r,o=[]){if(!S(e)){r.push({path:t,message:"页应为对象"});return}const n=e.pageWidthMm,s=e.pageHeightMm;(typeof n!="number"||!Number.isFinite(n)||n<=0)&&r.push({path:`${t}.pageWidthMm`,message:`页宽非法: ${JSON.stringify(n)}`}),(typeof s!="number"||!(s>0&&s<5e3))&&r.push({path:`${t}.pageHeightMm`,message:`页高非法: ${JSON.stringify(s)}`}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${t}.layout`,message:"布局应为 page 或 wide"});const i=e.components;Array.isArray(i)?Array.isArray(i)&&i.forEach((m,h)=>F(m,`${t}.components.${h}`,r,o)):r.push({path:`${t}.components`,message:"components 应为数组"})}function ee(e){const t=[],r=[],o=S(e)?e.pages:void 0;if(S(e)&&e.requiresRecalculation!==void 0&&typeof e.requiresRecalculation!="boolean"&&t.push({path:"$.requiresRecalculation",message:"重算能力要求应为布尔值"}),!Array.isArray(o))t.push({path:"$.pages",message:e==null?"渲染计划为空":"渲染计划缺少 pages 数组"});else{o.forEach((s,i)=>Y(s,`$.pages.${i}`,t,r)),o.length>2e3&&r.push({path:"$.pages",message:`页数异常大(${o.length} 页),渲染与打印耗时可能显著增加`});const n=o.reduce((s,i)=>s+(S(i)&&Array.isArray(i.components)?i.components.length:0),0);n>5e4&&r.push({path:"$.pages",message:`组件总数异常大(${n} 个),可能触发浏览器性能限制`})}return{ok:t.length===0,errors:t,warnings:r}}const E="mach-report-worker/1";class B extends Error{constructor(t){super(t.message),this.name=t.name,this.code=t.code,this.path=t.path,this.issues=t.issues,this.diagnostics=t.diagnostics}}function v(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function te(e){return v(e)?["rows","pages","cells"].every(t=>typeof e[t]=="number"&&Number.isSafeInteger(e[t])&&e[t]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function re(e){return Array.isArray(e)&&e.every(t=>v(t)&&typeof t.code=="string"&&typeof t.message=="string"&&["info","warning","error"].includes(t.severity))}function ne(e){return v(e)&&Object.values(e).every(t=>v(t)&&(t.revision===void 0||typeof t.revision=="string")&&(t.sourceToken===void 0||typeof t.sourceToken=="string"))}function oe(e,t){if(!v(e)||!te(e.stats)||!re(e.diagnostics)||!ne(e.revisions))return!1;if(t==="prepare")return ee(e.plan).ok;const r=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===r}function U(e){if(!e||typeof e!="object")return{message:String(e)};const t={};for(const r of["code","path","field","message"]){const o=e[r];typeof o=="string"&&(t[r]=o)}return t}function se(e){const t=U(e);if(!v(e))return t;for(const r of["format","severity","kind","nid"])typeof e[r]=="string"&&(t[r]=e[r]);for(const r of["pageIndex","componentIndex"])Number.isSafeInteger(e[r])&&e[r]>=0&&(t[r]=e[r]);return Array.isArray(e.componentPath)&&e.componentPath.every(r=>Number.isSafeInteger(r)&&r>=0)&&(t.componentPath=e.componentPath),t}function ie(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const t=e;return{name:e.name,message:e.message,...typeof t.code=="string"?{code:t.code}:{},...typeof t.path=="string"?{path:t.path}:{},...Array.isArray(t.issues)?{issues:t.issues.map(U)}:{},...Array.isArray(t.diagnostics)?{diagnostics:t.diagnostics.map(se)}:{}}}function ae(e){if(!e||typeof e!="object")return!1;const t=e;return t.protocol===E&&typeof t.id=="string"&&(t.operation==="prepare"||t.operation==="export")&&!!t.input&&typeof t.input=="object"}async function ce(e,t,r){try{const o=t.operation==="prepare"?await e.prepare({...t.input,onEvent:r}):await e.export({...t.input,onEvent:r});return{protocol:E,id:t.id,result:o}}catch(o){return{protocol:E,id:t.id,error:ie(o)}}}function fe(e){const t=e.result;return!t||!("bytes"in t)||!(t.bytes.buffer instanceof ArrayBuffer)?[]:[t.bytes.buffer]}function ue(e,t){if(!v(e)||typeof e.taskId!="string"||!e.taskId||t.taskId!==void 0&&e.taskId!==t.taskId||e.correlationId!==t.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!t.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const r of["completed","total"])if(e[r]!==void 0&&(typeof e[r]!="number"||!Number.isFinite(e[r])||e[r]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let pe=0;function P(e){const t=new Error("报表 Worker 任务已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e}),t}function de(e,t){if(!e||typeof e!="object")return;const r=e;return r.protocol===E&&r.id===t?r:void 0}function me(e,t={}){const r=t.timeoutMs??12e4;if(!Number.isFinite(r)||r<=0||r>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(n,s,i,m)=>i?.aborted?Promise.reject(P(i.reason)):new Promise((h,u)=>{let b;try{b=e()}catch(y){u(y);return}const x=`mach-report-${Date.now()}-${++pe}`;let p=!1,f=()=>{},c;const d=(y,w)=>{p||(p=!0,c&&clearTimeout(c),f(),i?.removeEventListener("abort",g),Promise.resolve().then(()=>b.terminate()).then(()=>y===void 0?h(w):u(y),$=>u(y??$)))},g=()=>d(P(i?.reason)),A=y=>{const w=de(y,x);if(!(!w||p)){if("type"in w&&w.type==="event"){const $="event"in w?w.event:void 0;ue($,s)?C(m,$,i):d(new Error("报表 Worker 返回无效阶段事件"));return}w.error&&typeof w.error.name=="string"&&typeof w.error.message=="string"?d(new B(w.error)):oe(w.result,n)&&(n!=="export"||"format"in w.result&&"format"in s&&w.result.format===s.format)?d(void 0,w.result):d(new Error("报表 Worker 返回无效响应"))}};try{if(f=b.subscribe(A,y=>d(y??new Error("报表 Worker 执行失败"))),p){f();return}if(i?.addEventListener("abort",g,{once:!0}),c=setTimeout(()=>d(new B({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${r}ms`})),r),i?.aborted)g();else{const{onEvent:y,signal:w,...$}=s;b.postMessage({protocol:E,id:x,operation:n,input:$})}}catch(y){d(y)}});return{prepare:(n,s,i)=>o("prepare",n,s,i),export:(n,s,i)=>o("export",n,s,i)}}const ye=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),k=(e,t)=>e>>>t|e<<32-t;function le(e,t,r){const o=new DataView(e.buffer,e.byteOffset+t,64);for(let n=0;n<16;n++)r[n]=o.getUint32(n*4);for(let n=16;n<64;n++){const s=r[n-15],i=r[n-2],m=k(s,7)^k(s,18)^s>>>3,h=k(i,17)^k(i,19)^i>>>10;r[n]=r[n-16]+m+r[n-7]+h}}function he(e,t){let r=e[0],o=e[1],n=e[2],s=e[3],i=e[4],m=e[5],h=e[6],u=e[7];for(let b=0;b<64;b++){const x=k(i,6)^k(i,11)^k(i,25),p=i&m^~i&h,f=u+x+p+ye[b]+t[b]>>>0,c=k(r,2)^k(r,13)^k(r,22),d=r&o^r&n^o&n,g=c+d>>>0;u=h,h=m,m=i,i=s+f>>>0,s=n,n=o,o=r,r=f+g>>>0}e[0]=e[0]+r,e[1]=e[1]+o,e[2]=e[2]+n,e[3]=e[3]+s,e[4]=e[4]+i,e[5]=e[5]+m,e[6]=e[6]+h,e[7]=e[7]+u}function ge(e){const t=new Uint8Array(Math.ceil((e.byteLength+9)/64)*64);t.set(e),t[e.byteLength]=128;const r=new DataView(t.buffer);return r.setUint32(t.length-8,Math.floor(e.byteLength/536870912)),r.setUint32(t.length-4,e.byteLength*8>>>0),t}const we=()=>new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),be=e=>Array.from(e,t=>t.toString(16).padStart(8,"0")).join("");async function Ae(e){const t=ge(e),r=we(),o=new Uint32Array(64);for(let n=0;n<t.length;n+=64)n>0&&n%262144===0&&await new Promise(s=>setTimeout(s,0)),le(t,n,o),he(r,o);return be(r)}class a extends Error{constructor(t,r){super(r),this.code=t,this.name="ReportJobError"}}function T(e,t){if(typeof e!="string"||!e.trim()||e.length>256||typeof t!="string"||!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(t))throw new a("input","任务范围应非空,ID应为1–128位安全标识")}function ke(e){const t=Array.isArray(e),r=Object.getPrototypeOf(e),o=Object.keys(e);if(r!==(t?Array.prototype:Object.prototype)&&!(r===null&&!t))throw new a("input","任务对象应为普通 JSON 对象");if(Object.getOwnPropertySymbols(e).length)throw new a("input","任务不能包含Symbol");if(Object.getOwnPropertyNames(e).filter(s=>!(t&&s==="length")).length!==o.length)throw new a("input","任务不能包含不可枚举属性");if(t&&(o.length!==e.length||o.some(s=>!/^(0|[1-9]\d*)$/.test(s)||Number(s)>=e.length)))throw new a("input","任务数组不能稀疏或包含额外属性");return o.sort()}function xe(e,t){const r=Object.getOwnPropertyDescriptor(e,t);if(["__proto__","prototype","constructor"].includes(t)||r.get||r.set)throw new a("input","任务不能包含危险键或访问器");return r.value}function N(e,t={}){const r=t.maxNodes??2e4,o=t.maxCharacters??1e6;if(!Number.isSafeInteger(r)||r<1||r>2e4||!Number.isSafeInteger(o)||o<1||o>1e6)throw new a("input","任务JSON预算无效");let n=0,s=0;const i=new Set;function m(u,b){if(++n>r||b>32)throw new a("input","任务数据超过节点或深度预算");if(typeof u=="string"){if(s+=u.length,s>o)throw new a("input","任务文本超过预算");return u}if(u===null||typeof u=="boolean"||typeof u=="number"&&Number.isFinite(u))return u;if(!u||typeof u!="object"||i.has(u))throw new a("input","任务只允许无循环的有限 JSON 值");const x=Array.isArray(u),p=ke(u);i.add(u);const f=Object.create(null);for(const c of p){if(s+=c.length,s>o)throw new a("input","任务文本超过预算");f[c]=m(xe(u,c),b+1)}return i.delete(u),x?Array.from({length:u.length},(c,d)=>f[String(d)]):f}const h=JSON.stringify(m(e,0));if(h.length>o)throw new a("input","任务序列化数据超过字符预算");return h}function J(e){return JSON.parse(JSON.stringify(e))}function _(e,t,r,o){if(T(t,r),e.scope!==t||e.id!==r||e.revision!==(o??0)+1||!Number.isSafeInteger(e.revision))throw new a("input","任务身份或修订不匹配");if(![e.createdAt,e.updatedAt,e.attempt].every(n=>Number.isSafeInteger(n)&&n>=0)||!["queued","running","completed","failed","cancelled"].includes(e.status))throw new a("input","任务状态无效");if(e.lease&&(!e.lease.owner||!Number.isSafeInteger(e.lease.expiresAt)))throw new a("input","任务租约无效");if(!e.request||typeof e.request.kind!="string"||!e.request.kind.trim()||e.request.kind.length>128)throw new a("input","任务类型无效");N(e.request.payload,{maxNodes:19e3,maxCharacters:75e4}),N(e)}function $e(e,t){if(e&&(e.createdAt!==t.createdAt||N(e.request)!==N(t.request)))throw new a("input","任务创建时间与请求不可变更,请使用新任务ID")}function Se(e,t){return e.status==="queued"||e.status==="running"&&(e.lease?.expiresAt??0)<=t}function Ne(e={}){const t={maxRecords:e.maxRecords??1e4,maxBytes:e.maxBytes??67108864,maxResultBytes:e.maxResultBytes??262144,controlReserveBytes:e.controlReserveBytes??4096,maxTombstones:e.maxTombstones??1e4,maxTombstoneBytes:e.maxTombstoneBytes??16777216};if(!Object.values(t).every(r=>Number.isSafeInteger(r)&&r>0)||t.controlReserveBytes<4096)throw new a("input","任务容量应为正整数,控制状态预留至少4096字节");return t}function O(e){return new TextEncoder().encode(N(e)).byteLength}function z(e,t){const r={scope:e.scope,id:e.id,revision:1,request:e.request,status:"queued",createdAt:e.createdAt,updatedAt:e.createdAt,attempt:0},o={...e};delete o.result;const n=e.result===void 0?0:O(e.result);if(n>t.maxResultBytes)throw new a("capacity","任务结果超过独立预算,请保存文件引用");return Math.max(O(r)+t.controlReserveBytes,O(o))+n}function L(e){return e.status!=="queued"&&e.status!=="running"}function Re(e){const t={...e,tombstoneRetentionMs:e.tombstoneRetentionMs??6048e5,limit:e.limit??100};if(![t.now,t.terminalBefore].every(r=>Number.isSafeInteger(r)&&r>=0)||t.terminalBefore>t.now)throw new a("input","终态清理时间应为不超过当前时间的非负整数");if(![t.tombstoneRetentionMs,t.limit].every(r=>Number.isSafeInteger(r)&&r>0)||!Number.isSafeInteger(t.now+t.tombstoneRetentionMs))throw new a("input","幂等保留期与清理批量应为正整数");return t}async function ve(e){const t=new TextEncoder().encode(N(e)),r=globalThis.crypto?.subtle;if(!r)return Ae(t);const o=await r.digest("SHA-256",t);return Array.from(new Uint8Array(o),n=>n.toString(16).padStart(2,"0")).join("")}async function Ee(e,t){if(!L(e))throw new a("input","只能归档终态任务");return{scope:e.scope,id:e.id,revision:e.revision,status:e.status,createdAt:e.createdAt,updatedAt:e.updatedAt,attempt:e.attempt,requestHash:await ve(e.request),expiresAt:t}}function Oe(e){if(!e||!["completed","failed","cancelled"].includes(e.status)||!/^[a-f0-9]{64}$/.test(e.requestHash))throw new a("input","任务幂等摘要无效");if(![e.revision,e.createdAt,e.updatedAt,e.attempt,e.expiresAt].every(t=>Number.isSafeInteger(t)&&t>=0)||e.revision<1)throw new a("input","任务幂等摘要时间或修订无效")}function I(e){return e?.code}function M(e,t){return j.createHash("sha256").update(JSON.stringify([e,t])).digest("hex")+".json"}async function q(e){try{return await l.promises.readFile(e,"utf8")}catch(t){if(I(t)==="ENOENT")return;throw t}}async function Me(e,t){const r=await q(e);if(r===void 0)return;let o;try{o=JSON.parse(r)}catch{throw new a("conflict","任务锁尚未完整写入或已损坏,拒绝自动移除")}if(!o||!Number.isSafeInteger(o.pid)||o.pid<1)throw new a("conflict","任务锁身份无效,拒绝自动移除");try{process.kill(o.pid,0)}catch(n){if(I(n)==="ESRCH"){await l.promises.unlink(e);return}throw n}throw new a("conflict","任务目录的写入进程仍在运行")}async function Ie(e,t){if(!t)throw new a("conflict","任务目录已有写入进程;多实例请使用数据库CAS适配器");const r=e+".recovery";let o;try{o=await l.promises.open(r,"wx",384)}catch(n){throw I(n)==="EEXIST"?new a("conflict","任务目录恢复正在进行,请稍后重试"):n}try{return await o.writeFile(JSON.stringify({pid:process.pid})),await Me(e,!0),await l.promises.open(e,"wx",384)}finally{await o.close(),await l.promises.unlink(r)}}async function Te(e,t){const r=R.join(e,".writer-lock"),o=j.randomUUID();let n;try{n=await l.promises.open(r,"wx",384)}catch(s){if(I(s)!=="EEXIST")throw s;n=await Ie(r,t)}try{await n.writeFile(JSON.stringify({pid:process.pid,token:o})),await n.sync()}catch(s){throw await n.close(),await l.promises.unlink(r).catch(()=>{}),s}return{file:r,token:o,handle:n}}function je(e,t,r,o){if("tombstone"in r){const n=r.tombstone;if(Oe(n),T(n.scope,n.id),M(n.scope,n.id)!==t)throw new a("input","持久任务摘要身份不匹配");const s=O(n);e.tombstoneBytes+=s,e.tombstones.set(t,{value:n,bytes:s})}else{if(_(r,r.scope,r.id,r.revision-1),M(r.scope,r.id)!==t)throw new a("input","持久任务文件身份不匹配");const n=z(r,o);e.bytes+=n,e.records.set(t,{record:r,bytes:n})}if(e.bytes>o.maxBytes||e.records.size>o.maxRecords||e.tombstoneBytes>o.maxTombstoneBytes||e.tombstones.size>o.maxTombstones)throw new a("capacity","持久任务及控制状态预留超过目录预算")}async function Je(e,t){const r=await l.promises.readdir(e);for(const s of r.filter(i=>/^\.pending-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(i)))await l.promises.unlink(R.join(e,s));const o=r.filter(s=>/^[a-f0-9]{64}\.json$/.test(s));if(o.length>t.maxRecords+t.maxTombstones)throw new a("capacity","持久任务数量超过目录预算");const n={records:new Map,tombstones:new Map,bytes:0,tombstoneBytes:0};for(const s of o){const i=R.join(e,s);if((await l.promises.stat(i)).size>4e6)throw new a("capacity","持久任务文件超过单文件预算");je(n,s,JSON.parse(await l.promises.readFile(i,"utf8")),t)}return n}async function Be(e,t,r){const o=R.join(e,`.pending-${j.randomUUID()}`);try{const n=await l.promises.open(o,"wx",384);try{await n.writeFile(r),await n.sync()}finally{await n.close()}await l.promises.rename(o,R.join(e,t));const s=await l.promises.open(e,"r");try{await s.sync()}finally{await s.close()}}finally{await l.promises.unlink(o).catch(n=>{if(I(n)!=="ENOENT")throw n})}}async function qe(e){const t=R.resolve(e.directory),r=Ne(e);await l.promises.mkdir(t,{recursive:!0,mode:448});const o=await Te(t,e.recoverDeadOwner??!1);let n;try{n=await Je(t,r)}catch(p){throw await o.handle.close(),await l.promises.unlink(o.file),p}let s=!1,i=Promise.resolve();const m=()=>{if(s)throw new a("closed","持久任务存储已关闭")},h=p=>{m();const f=i.then(async()=>{if(JSON.parse(await l.promises.readFile(o.file,"utf8")).token!==o.token)throw new a("closed","持久任务存储写入锁已失效");return p()});return i=f.then(()=>{},()=>{}),f},u=async(p,f,c)=>{try{await Be(t,p,f)}catch(d){throw await q(R.join(t,p))===f&&c(),d}c()};return{read:async(p,f)=>{m(),T(p,f),await i;const c=n.records.get(M(p,f));return c?J(c.record):void 0},readTombstone:async(p,f)=>{m(),T(p,f),await i;const c=n.tombstones.get(M(p,f));return c?J(c.value):void 0},candidates:async(p,f)=>(m(),await i,Array.from(n.records.values(),c=>c.record).filter(c=>Se(c,p)).sort((c,d)=>c.createdAt-d.createdAt).slice(0,f).map(J)),compareAndSwap:async(p,f,c,d)=>{const g=JSON.parse(N(d));return _(g,p,f,c),h(async()=>{const A=M(p,f),y=n.records.get(A);if((y?.record.revision??null)!==c||n.tombstones.has(A))return!1;$e(y?.record,g);const w=z(g,r),$=n.bytes-(y?.bytes??0)+w;if($>r.maxBytes||!y&&n.records.size>=r.maxRecords)throw new a("capacity","持久任务容量已满,请清理终态任务或扩大显式预算");return await u(A,N(g),()=>{n.records.set(A,{record:g,bytes:w}),n.bytes=$}),!0})},prune:async p=>{const f=Re(p);return h(async()=>{const c={archived:0,expired:0};for(const[d,g]of n.tombstones)g.value.expiresAt>f.now||c.expired>=f.limit||(await l.promises.unlink(R.join(t,d)),n.tombstones.delete(d),n.tombstoneBytes-=g.bytes,c.expired++);for(const[d,g]of n.records){if(!L(g.record)||g.record.updatedAt>f.terminalBefore||c.archived+c.expired>=f.limit)continue;const A=await Ee(g.record,f.now+f.tombstoneRetentionMs),y=O(A);if(n.tombstones.size>=r.maxTombstones||n.tombstoneBytes+y>r.maxTombstoneBytes)break;await u(d,N({tombstone:A}),()=>{n.tombstones.set(d,{value:A,bytes:y}),n.tombstoneBytes+=y,n.records.delete(d),n.bytes-=g.bytes}),c.archived++}if(c.expired){const d=await l.promises.open(t,"r");try{await d.sync()}finally{await d.close()}}return c})},close:async()=>{if(s)return;s=!0,await i,await o.handle.close();const p=await q(o.file);p&&JSON.parse(p).token===o.token&&await l.promises.unlink(o.file)}}}function Pe(e){const t=e.filename??e.workerUrl;if(!t||e.filename&&e.workerUrl)throw new TypeError("请且仅请指定 filename 或 workerUrl");return me(()=>{const r=new W.Worker(t,e.workerOptions);return{postMessage:o=>r.postMessage(o),terminate:()=>r.terminate(),subscribe:(o,n)=>{const s=i=>n(new Error(`报表 Worker 在响应前退出(code ${i})`));return r.on("message",o),r.on("error",n),r.on("messageerror",n),r.on("exit",s),()=>{r.off("message",o),r.off("error",n),r.off("messageerror",n),r.off("exit",s)}}}},e)}function We(e){const t=W.parentPort;if(!t)throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");const r=o=>{ae(o)&&ce(e,o,n=>t.postMessage({protocol:E,id:o.id,type:"event",event:n})).then(n=>t.postMessage(n,fe(n)))};return t.on("message",r),()=>t.off("message",r)}function De(e){return j.createHash("sha256").update(e).digest("hex")}exports.ReportWorkerError=B;exports.createNodeReportExecutor=Pe;exports.openFileReportJobStore=qe;exports.reportArtifactSha256=De;exports.serveNodeReportWorker=We;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("node:worker_threads"),j=require("node:crypto"),l=require("node:fs"),R=require("node:path");function C(e,t,n){if(!n?.aborted)try{const o=e?.({...t});o&&typeof o.then=="function"&&Promise.resolve(o).catch(()=>{})}catch{}}function H(e,t,n){e.editable!==void 0&&typeof e.editable!="boolean"&&n.push({path:`${t}.editable`,message:"编辑控制应为布尔值"}),e.valueType!==void 0&&!["text","number","boolean"].includes(e.valueType)&&n.push({path:`${t}.valueType`,message:"编辑类型应为 text、number 或 boolean"})}function K(e,t,n){H(e,t,n),e.indentMm!==void 0&&(typeof e.indentMm!="number"||!Number.isFinite(e.indentMm)||e.indentMm<0)&&n.push({path:`${t}.indentMm`,message:"单元格缩进应为有限非负数"}),e.derived!==void 0&&typeof e.derived!="boolean"&&n.push({path:`${t}.derived`,message:"派生结果标记应为布尔值"}),F(e.source,`${t}.source`,n,!0),e.formula!==void 0&&typeof e.formula!="string"&&n.push({path:`${t}.formula`,message:"单元格公式应为字符串"})}function F(e,t,n,o=!1){if(e===void 0)return;if(!e||typeof e!="object"||Array.isArray(e)){n.push({path:t,message:"业务来源应为对象"});return}const r=e;for(const s of["datasetId",...o?["field"]:[]])(typeof r[s]!="string"||!r[s].trim())&&n.push({path:`${t}.${s}`,message:"业务标识应为非空字符串"});for(const s of["rowKey","revision"]){const i=r[s];i===void 0&&!(o&&s==="rowKey")||typeof i!="string"&&!(typeof i=="number"&&Number.isFinite(i))&&n.push({path:`${t}.${s}`,message:"业务键及修订号应为字符串或有限数字"})}r.sourceToken!==void 0&&typeof r.sourceToken!="string"&&n.push({path:`${t}.sourceToken`,message:"来源令牌应为字符串"})}const V=new Set(["text","image","barcode","qrcode","chart","line","rect","ellipse"]);function N(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function G(e,t,n,o){const r=e[t];(typeof r!="number"||!Number.isFinite(r))&&o.push({path:`${n}.${t}`,message:`应为有限数字,实际 ${JSON.stringify(r)}`})}function X(e,t,n){if(e!==void 0){const o=`${t}.table`;if(!N(e))n.push({path:o,message:"逻辑表来源应为对象"});else{F(e.source,`${o}.source`,n),(typeof e.id!="string"||!e.id.trim())&&n.push({path:`${o}.id`,message:"逻辑表 ID 应为非空字符串"});const r=e.role;["header","body","group-header","subtotal","grand-total"].includes(r)||n.push({path:`${o}.role`,message:"未知逻辑表行角色"});const s=e.rowIndex;(typeof s!="number"||!Number.isInteger(s)||(r==="header"?s!==-1:s<0))&&n.push({path:`${o}.rowIndex`,message:"表头索引应为 -1,内容行索引应为非负整数"}),(!Array.isArray(e.columnKeys)||e.columnKeys.some(i=>typeof i!="string"))&&n.push({path:`${o}.columnKeys`,message:"逻辑列字段应为字符串数组"}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&n.push({path:`${o}.layout`,message:"布局应为 page 或 wide"}),e.title!==void 0&&typeof e.title!="string"&&n.push({path:`${o}.title`,message:"逻辑表名称应为字符串"})}}}function Z(e,t,n,o){if(e!==void 0)if(!N(e)||!Array.isArray(e.cells))n.push({path:`${t}.grid.cells`,message:"grid.cells 应为二维数组"});else{const r=e.paddingMm;r!==void 0&&(typeof r!="number"||!Number.isFinite(r)||r<0)&&n.push({path:`${t}.grid.paddingMm`,message:"单元格内距应为有限非负数"}),e.cells.forEach((s,i)=>{if(!Array.isArray(s)){n.push({path:`${t}.grid.cells.${i}`,message:"行应为数组"});return}s.forEach((m,h)=>{if(m==null)return;const u=`${t}.grid.cells.${i}.${h}`;if(!N(m)){n.push({path:u,message:"网格单元格应为对象或 null"});return}K(m,u,n),Array.isArray(m.children)&&m.children.forEach((b,x)=>{D(b,`${t}.grid.cells.${i}.${h}.children.${x}`,n,o)})})})}}function Q(e,t,n){e!==void 0&&(Array.isArray(e)?e.forEach((o,r)=>{(!N(o)||!Array.isArray(o.segments))&&n.push({path:`${t}.richParagraphs.${r}`,message:"段落缺少 segments 数组"})}):n.push({path:`${t}.richParagraphs`,message:"richParagraphs 应为数组"}))}function D(e,t,n,o=[]){if(!N(e)){n.push({path:t,message:"组件应为对象"});return}const r=e.kind;typeof r!="string"?n.push({path:`${t}.kind`,message:"组件缺少 kind 字符串"}):V.has(r)||o.push({path:`${t}.kind`,message:`未知组件类型 ${JSON.stringify(r)},将以兜底方式渲染`});for(const s of["leftMm","topMm","widthMm","heightMm"])G(e,s,t,n);typeof e.leftMm=="number"&&e.leftMm<-100&&n.push({path:`${t}.leftMm`,message:"几何数值异常(leftMm<-100)"});for(const s of["widthMm","heightMm"])typeof e[s]=="number"&&e[s]<0&&n.push({path:`${t}.${s}`,message:"组件尺寸不能为负数"});X(e.table,t,n),e.pageAnchor!==void 0&&!["header","footer"].includes(e.pageAnchor)&&n.push({path:`${t}.pageAnchor`,message:"页面锚点应为 header 或 footer"}),e.lineDirection!==void 0&&!["down","up"].includes(e.lineDirection)&&n.push({path:`${t}.lineDirection`,message:"线段方向应为 down 或 up"}),Z(e.grid,t,n,o),Q(e.richParagraphs,t,n)}function Y(e,t,n,o=[]){if(!N(e)){n.push({path:t,message:"页应为对象"});return}const r=e.pageWidthMm,s=e.pageHeightMm;(typeof r!="number"||!Number.isFinite(r)||r<=0)&&n.push({path:`${t}.pageWidthMm`,message:`页宽非法: ${JSON.stringify(r)}`}),(typeof s!="number"||!(s>0&&s<5e3))&&n.push({path:`${t}.pageHeightMm`,message:`页高非法: ${JSON.stringify(s)}`}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&n.push({path:`${t}.layout`,message:"布局应为 page 或 wide"});const i=e.components;Array.isArray(i)?Array.isArray(i)&&i.forEach((m,h)=>D(m,`${t}.components.${h}`,n,o)):n.push({path:`${t}.components`,message:"components 应为数组"})}function ee(e){const t=[],n=[],o=N(e)?e.pages:void 0;if(N(e)&&e.requiresRecalculation!==void 0&&typeof e.requiresRecalculation!="boolean"&&t.push({path:"$.requiresRecalculation",message:"重算能力要求应为布尔值"}),!Array.isArray(o))t.push({path:"$.pages",message:e==null?"渲染计划为空":"渲染计划缺少 pages 数组"});else{o.forEach((s,i)=>Y(s,`$.pages.${i}`,t,n)),o.length>2e3&&n.push({path:"$.pages",message:`页数异常大(${o.length} 页),渲染与打印耗时可能显著增加`});const r=o.reduce((s,i)=>s+(N(i)&&Array.isArray(i.components)?i.components.length:0),0);r>5e4&&n.push({path:"$.pages",message:`组件总数异常大(${r} 个),可能触发浏览器性能限制`})}return{ok:t.length===0,errors:t,warnings:n}}const E="mach-report-worker/1";class B extends Error{constructor(t){super(t.message),this.name=t.name,this.code=t.code,this.path=t.path,this.issues=t.issues,this.diagnostics=t.diagnostics}}function v(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function te(e){return v(e)?["rows","pages","cells"].every(t=>typeof e[t]=="number"&&Number.isSafeInteger(e[t])&&e[t]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function ne(e){return Array.isArray(e)&&e.every(t=>v(t)&&typeof t.code=="string"&&typeof t.message=="string"&&["info","warning","error"].includes(t.severity))}function re(e){return v(e)&&Object.values(e).every(t=>v(t)&&(t.revision===void 0||typeof t.revision=="string")&&(t.sourceToken===void 0||typeof t.sourceToken=="string"))}function oe(e,t){if(!v(e)||!te(e.stats)||!ne(e.diagnostics)||!re(e.revisions))return!1;if(t==="prepare")return ee(e.plan).ok;const n=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===n}function U(e){if(!e||typeof e!="object")return{message:String(e)};const t={};for(const n of["code","path","field","message"]){const o=e[n];typeof o=="string"&&(t[n]=o)}return t}function se(e){const t=U(e);if(!v(e))return t;for(const n of["format","severity","kind","nid"])typeof e[n]=="string"&&(t[n]=e[n]);for(const n of["pageIndex","componentIndex"])Number.isSafeInteger(e[n])&&e[n]>=0&&(t[n]=e[n]);return Array.isArray(e.componentPath)&&e.componentPath.every(n=>Number.isSafeInteger(n)&&n>=0)&&(t.componentPath=e.componentPath),t}function ie(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const t=e;return{name:e.name,message:e.message,...typeof t.code=="string"?{code:t.code}:{},...typeof t.path=="string"?{path:t.path}:{},...Array.isArray(t.issues)?{issues:t.issues.map(U)}:{},...Array.isArray(t.diagnostics)?{diagnostics:t.diagnostics.map(se)}:{}}}function ae(e){if(!e||typeof e!="object")return!1;const t=e;return t.protocol===E&&typeof t.id=="string"&&(t.operation==="prepare"||t.operation==="export")&&!!t.input&&typeof t.input=="object"}async function ce(e,t,n){try{const o=t.operation==="prepare"?await e.prepare({...t.input,onEvent:n}):await e.export({...t.input,onEvent:n});return{protocol:E,id:t.id,result:o}}catch(o){return{protocol:E,id:t.id,error:ie(o)}}}function fe(e){const t=e.result;return!t||!("bytes"in t)||!(t.bytes.buffer instanceof ArrayBuffer)?[]:[t.bytes.buffer]}function ue(e,t){if(!v(e)||typeof e.taskId!="string"||!e.taskId||t.taskId!==void 0&&e.taskId!==t.taskId||e.correlationId!==t.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!t.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const n of["completed","total"])if(e[n]!==void 0&&(typeof e[n]!="number"||!Number.isFinite(e[n])||e[n]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let pe=0;function P(e){const t=new Error("报表 Worker 任务已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e}),t}function de(e,t){if(!e||typeof e!="object")return;const n=e;return n.protocol===E&&n.id===t?n:void 0}function me(e,t={}){const n=t.timeoutMs??12e4;if(!Number.isFinite(n)||n<=0||n>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(r,s,i,m)=>i?.aborted?Promise.reject(P(i.reason)):new Promise((h,u)=>{let b;try{b=e()}catch(y){u(y);return}const x=`mach-report-${Date.now()}-${++pe}`;let p=!1,f=()=>{},c;const d=(y,w)=>{p||(p=!0,c&&clearTimeout(c),f(),i?.removeEventListener("abort",g),Promise.resolve().then(()=>b.terminate()).then(()=>y===void 0?h(w):u(y),$=>u(y??$)))},g=()=>d(P(i?.reason)),A=y=>{const w=de(y,x);if(!(!w||p)){if("type"in w&&w.type==="event"){const $="event"in w?w.event:void 0;ue($,s)?C(m,$,i):d(new Error("报表 Worker 返回无效阶段事件"));return}w.error&&typeof w.error.name=="string"&&typeof w.error.message=="string"?d(new B(w.error)):oe(w.result,r)&&(r!=="export"||"format"in w.result&&"format"in s&&w.result.format===s.format)?d(void 0,w.result):d(new Error("报表 Worker 返回无效响应"))}};try{if(f=b.subscribe(A,y=>d(y??new Error("报表 Worker 执行失败"))),p){f();return}if(i?.addEventListener("abort",g,{once:!0}),c=setTimeout(()=>d(new B({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${n}ms`})),n),i?.aborted)g();else{const{onEvent:y,signal:w,...$}=s;b.postMessage({protocol:E,id:x,operation:r,input:$})}}catch(y){d(y)}});return{prepare:(r,s,i)=>o("prepare",r,s,i),export:(r,s,i)=>o("export",r,s,i)}}const ye=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),k=(e,t)=>e>>>t|e<<32-t;function le(e,t,n){const o=new DataView(e.buffer,e.byteOffset+t,64);for(let r=0;r<16;r++)n[r]=o.getUint32(r*4);for(let r=16;r<64;r++){const s=n[r-15],i=n[r-2],m=k(s,7)^k(s,18)^s>>>3,h=k(i,17)^k(i,19)^i>>>10;n[r]=n[r-16]+m+n[r-7]+h}}function he(e,t){let n=e[0],o=e[1],r=e[2],s=e[3],i=e[4],m=e[5],h=e[6],u=e[7];for(let b=0;b<64;b++){const x=k(i,6)^k(i,11)^k(i,25),p=i&m^~i&h,f=u+x+p+ye[b]+t[b]>>>0,c=k(n,2)^k(n,13)^k(n,22),d=n&o^n&r^o&r,g=c+d>>>0;u=h,h=m,m=i,i=s+f>>>0,s=r,r=o,o=n,n=f+g>>>0}e[0]=e[0]+n,e[1]=e[1]+o,e[2]=e[2]+r,e[3]=e[3]+s,e[4]=e[4]+i,e[5]=e[5]+m,e[6]=e[6]+h,e[7]=e[7]+u}function ge(e){const t=new Uint8Array(Math.ceil((e.byteLength+9)/64)*64);t.set(e),t[e.byteLength]=128;const n=new DataView(t.buffer);return n.setUint32(t.length-8,Math.floor(e.byteLength/536870912)),n.setUint32(t.length-4,e.byteLength*8>>>0),t}const we=()=>new Uint32Array([1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225]),be=e=>Array.from(e,t=>t.toString(16).padStart(8,"0")).join("");async function Ae(e){const t=ge(e),n=we(),o=new Uint32Array(64);for(let r=0;r<t.length;r+=64)r>0&&r%262144===0&&await new Promise(s=>setTimeout(s,0)),le(t,r,o),he(n,o);return be(n)}class a extends Error{constructor(t,n){super(n),this.code=t,this.name="ReportJobError"}}function T(e,t){if(typeof e!="string"||!e.trim()||e.length>256||typeof t!="string"||t!==t.trim()||!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(t))throw new a("input","任务范围应非空,ID应为1–128位安全标识")}function ke(e){const t=Array.isArray(e),n=Object.getPrototypeOf(e),o=Object.keys(e);if(n!==(t?Array.prototype:Object.prototype)&&!(n===null&&!t))throw new a("input","任务对象应为普通 JSON 对象");if(Object.getOwnPropertySymbols(e).length)throw new a("input","任务不能包含Symbol");if(Object.getOwnPropertyNames(e).filter(s=>!(t&&s==="length")).length!==o.length)throw new a("input","任务不能包含不可枚举属性");if(t&&(o.length!==e.length||o.some(s=>s!==String(Number(s))||!Number.isSafeInteger(Number(s))||Number(s)<0||Number(s)>=e.length)))throw new a("input","任务数组不能稀疏或包含额外属性");return o.sort()}function xe(e,t){const n=Object.getOwnPropertyDescriptor(e,t);if(["__proto__","prototype","constructor"].includes(t)||n.get||n.set)throw new a("input","任务不能包含危险键或访问器");return n.value}function S(e,t={}){const n=t.maxNodes??2e4,o=t.maxCharacters??1e6;if(!Number.isSafeInteger(n)||n<1||n>2e4||!Number.isSafeInteger(o)||o<1||o>1e6)throw new a("input","任务JSON预算无效");let r=0,s=0;const i=new Set;function m(u,b){if(++r>n||b>32)throw new a("input","任务数据超过节点或深度预算");if(typeof u=="string"){if(s+=u.length,s>o)throw new a("input","任务文本超过预算");return u}if(u===null||typeof u=="boolean"||typeof u=="number"&&Number.isFinite(u))return u;if(!u||typeof u!="object"||i.has(u))throw new a("input","任务只允许无循环的有限 JSON 值");const x=Array.isArray(u),p=ke(u);i.add(u);const f=Object.create(null);for(const c of p){if(s+=c.length,s>o)throw new a("input","任务文本超过预算");f[c]=m(xe(u,c),b+1)}return i.delete(u),x?Array.from({length:u.length},(c,d)=>f[String(d)]):f}const h=JSON.stringify(m(e,0));if(h.length>o)throw new a("input","任务序列化数据超过字符预算");return h}function J(e){return JSON.parse(JSON.stringify(e))}function _(e,t,n,o){if(T(t,n),e.scope!==t||e.id!==n||e.revision!==(o??0)+1||!Number.isSafeInteger(e.revision))throw new a("input","任务身份或修订不匹配");if(![e.createdAt,e.updatedAt,e.attempt].every(r=>Number.isSafeInteger(r)&&r>=0)||!["queued","running","completed","failed","cancelled"].includes(e.status))throw new a("input","任务状态无效");if(e.lease&&(!e.lease.owner||!Number.isSafeInteger(e.lease.expiresAt)))throw new a("input","任务租约无效");if(!e.request||typeof e.request.kind!="string"||!e.request.kind.trim()||e.request.kind.length>128)throw new a("input","任务类型无效");S(e.request.payload,{maxNodes:19e3,maxCharacters:75e4}),S(e)}function $e(e,t){if(e&&(e.createdAt!==t.createdAt||S(e.request)!==S(t.request)))throw new a("input","任务创建时间与请求不可变更,请使用新任务ID")}function Ne(e,t){return e.status==="queued"||e.status==="running"&&(e.lease?.expiresAt??0)<=t}function Se(e={}){const t={maxRecords:e.maxRecords??1e4,maxBytes:e.maxBytes??67108864,maxResultBytes:e.maxResultBytes??262144,controlReserveBytes:e.controlReserveBytes??4096,maxTombstones:e.maxTombstones??1e4,maxTombstoneBytes:e.maxTombstoneBytes??16777216};if(!Object.values(t).every(n=>Number.isSafeInteger(n)&&n>0)||t.controlReserveBytes<4096)throw new a("input","任务容量应为正整数,控制状态预留至少4096字节");return t}function M(e){return new TextEncoder().encode(S(e)).byteLength}function z(e,t){const n={scope:e.scope,id:e.id,revision:1,request:e.request,status:"queued",createdAt:e.createdAt,updatedAt:e.createdAt,attempt:0},o={...e};delete o.result;const r=e.result===void 0?0:M(e.result);if(r>t.maxResultBytes)throw new a("capacity","任务结果超过独立预算,请保存文件引用");return Math.max(M(n)+t.controlReserveBytes,M(o))+r}function L(e){return e.status!=="queued"&&e.status!=="running"}function Re(e){const t={...e,tombstoneRetentionMs:e.tombstoneRetentionMs??6048e5,limit:e.limit??100};if(![t.now,t.terminalBefore].every(n=>Number.isSafeInteger(n)&&n>=0)||t.terminalBefore>t.now)throw new a("input","终态清理时间应为不超过当前时间的非负整数");if(![t.tombstoneRetentionMs,t.limit].every(n=>Number.isSafeInteger(n)&&n>0)||!Number.isSafeInteger(t.now+t.tombstoneRetentionMs))throw new a("input","幂等保留期与清理批量应为正整数");return t}async function ve(e){const t=new TextEncoder().encode(S(e)),n=globalThis.crypto?.subtle;if(!n)return Ae(t);const o=await n.digest("SHA-256",t);return Array.from(new Uint8Array(o),r=>r.toString(16).padStart(2,"0")).join("")}async function Ee(e,t){if(!L(e))throw new a("input","只能归档终态任务");return{scope:e.scope,id:e.id,revision:e.revision,status:e.status,createdAt:e.createdAt,updatedAt:e.updatedAt,attempt:e.attempt,requestHash:await ve(e.request),expiresAt:t}}function Me(e){if(!e||!["completed","failed","cancelled"].includes(e.status)||!/^[a-f0-9]{64}$/.test(e.requestHash))throw new a("input","任务幂等摘要无效");if(![e.revision,e.createdAt,e.updatedAt,e.attempt,e.expiresAt].every(t=>Number.isSafeInteger(t)&&t>=0)||e.revision<1)throw new a("input","任务幂等摘要时间或修订无效")}function I(e){return e?.code}function O(e,t){return j.createHash("sha256").update(JSON.stringify([e,t])).digest("hex")+".json"}async function q(e){try{return await l.promises.readFile(e,"utf8")}catch(t){if(I(t)==="ENOENT")return;throw t}}async function Oe(e,t){const n=await q(e);if(n===void 0)return;let o;try{o=JSON.parse(n)}catch{throw new a("conflict","任务锁尚未完整写入或已损坏,拒绝自动移除")}if(!o||!Number.isSafeInteger(o.pid)||o.pid<1)throw new a("conflict","任务锁身份无效,拒绝自动移除");try{process.kill(o.pid,0)}catch(r){if(I(r)==="ESRCH"){await l.promises.unlink(e);return}throw r}throw new a("conflict","任务目录的写入进程仍在运行")}async function Ie(e,t){if(!t)throw new a("conflict","任务目录已有写入进程;多实例请使用数据库CAS适配器");const n=e+".recovery";let o;try{o=await l.promises.open(n,"wx",384)}catch(r){throw I(r)==="EEXIST"?new a("conflict","任务目录恢复正在进行,请稍后重试"):r}try{return await o.writeFile(JSON.stringify({pid:process.pid})),await Oe(e,!0),await l.promises.open(e,"wx",384)}finally{await o.close(),await l.promises.unlink(n)}}async function Te(e,t){const n=R.join(e,".writer-lock"),o=j.randomUUID();let r;try{r=await l.promises.open(n,"wx",384)}catch(s){if(I(s)!=="EEXIST")throw s;r=await Ie(n,t)}try{await r.writeFile(JSON.stringify({pid:process.pid,token:o})),await r.sync()}catch(s){throw await r.close(),await l.promises.unlink(n).catch(()=>{}),s}return{file:n,token:o,handle:r}}function je(e,t,n,o){if("tombstone"in n){const r=n.tombstone;if(Me(r),T(r.scope,r.id),O(r.scope,r.id)!==t)throw new a("input","持久任务摘要身份不匹配");const s=M(r);e.tombstoneBytes+=s,e.tombstones.set(t,{value:r,bytes:s})}else{if(_(n,n.scope,n.id,n.revision-1),O(n.scope,n.id)!==t)throw new a("input","持久任务文件身份不匹配");const r=z(n,o);e.bytes+=r,e.records.set(t,{record:n,bytes:r})}if(e.bytes>o.maxBytes||e.records.size>o.maxRecords||e.tombstoneBytes>o.maxTombstoneBytes||e.tombstones.size>o.maxTombstones)throw new a("capacity","持久任务及控制状态预留超过目录预算")}async function Je(e,t){const n=await l.promises.readdir(e);for(const s of n.filter(i=>/^\.pending-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(i)))await l.promises.unlink(R.join(e,s));const o=n.filter(s=>/^[a-f0-9]{64}\.json$/.test(s));if(o.length>t.maxRecords+t.maxTombstones)throw new a("capacity","持久任务数量超过目录预算");const r={records:new Map,tombstones:new Map,bytes:0,tombstoneBytes:0};for(const s of o){const i=R.join(e,s);if((await l.promises.stat(i)).size>4e6)throw new a("capacity","持久任务文件超过单文件预算");je(r,s,JSON.parse(await l.promises.readFile(i,"utf8")),t)}return r}async function Be(e,t,n){const o=R.join(e,`.pending-${j.randomUUID()}`);try{const r=await l.promises.open(o,"wx",384);try{await r.writeFile(n),await r.sync()}finally{await r.close()}await l.promises.rename(o,R.join(e,t));const s=await l.promises.open(e,"r");try{await s.sync()}finally{await s.close()}}finally{await l.promises.unlink(o).catch(r=>{if(I(r)!=="ENOENT")throw r})}}async function qe(e){const t=R.resolve(e.directory),n=Se(e);await l.promises.mkdir(t,{recursive:!0,mode:448});const o=await Te(t,e.recoverDeadOwner??!1);let r;try{r=await Je(t,n)}catch(p){throw await o.handle.close(),await l.promises.unlink(o.file),p}let s=!1,i=Promise.resolve();const m=()=>{if(s)throw new a("closed","持久任务存储已关闭")},h=p=>{m();const f=i.then(async()=>{if(JSON.parse(await l.promises.readFile(o.file,"utf8")).token!==o.token)throw new a("closed","持久任务存储写入锁已失效");return p()});return i=f.then(()=>{},()=>{}),f},u=async(p,f,c)=>{try{await Be(t,p,f)}catch(d){throw await q(R.join(t,p))===f&&c(),d}c()};return{read:async(p,f)=>{m(),T(p,f),await i;const c=r.records.get(O(p,f));return c?J(c.record):void 0},readTombstone:async(p,f)=>{m(),T(p,f),await i;const c=r.tombstones.get(O(p,f));return c?J(c.value):void 0},candidates:async(p,f)=>(m(),await i,Array.from(r.records.values(),c=>c.record).filter(c=>Ne(c,p)).sort((c,d)=>c.createdAt-d.createdAt).slice(0,f).map(J)),compareAndSwap:async(p,f,c,d)=>{const g=JSON.parse(S(d));return _(g,p,f,c),h(async()=>{const A=O(p,f),y=r.records.get(A);if((y?.record.revision??null)!==c||r.tombstones.has(A))return!1;$e(y?.record,g);const w=z(g,n),$=r.bytes-(y?.bytes??0)+w;if($>n.maxBytes||!y&&r.records.size>=n.maxRecords)throw new a("capacity","持久任务容量已满,请清理终态任务或扩大显式预算");return await u(A,S(g),()=>{r.records.set(A,{record:g,bytes:w}),r.bytes=$}),!0})},prune:async p=>{const f=Re(p);return h(async()=>{const c={archived:0,expired:0};for(const[d,g]of r.tombstones)g.value.expiresAt>f.now||c.expired>=f.limit||(await l.promises.unlink(R.join(t,d)),r.tombstones.delete(d),r.tombstoneBytes-=g.bytes,c.expired++);for(const[d,g]of r.records){if(!L(g.record)||g.record.updatedAt>f.terminalBefore||c.archived+c.expired>=f.limit)continue;const A=await Ee(g.record,f.now+f.tombstoneRetentionMs),y=M(A);if(r.tombstones.size>=n.maxTombstones||r.tombstoneBytes+y>n.maxTombstoneBytes)break;await u(d,S({tombstone:A}),()=>{r.tombstones.set(d,{value:A,bytes:y}),r.tombstoneBytes+=y,r.records.delete(d),r.bytes-=g.bytes}),c.archived++}if(c.expired){const d=await l.promises.open(t,"r");try{await d.sync()}finally{await d.close()}}return c})},close:async()=>{if(s)return;s=!0,await i,await o.handle.close();const p=await q(o.file);p&&JSON.parse(p).token===o.token&&await l.promises.unlink(o.file)}}}function Pe(e){const t=e.filename??e.workerUrl;if(!t||e.filename&&e.workerUrl)throw new TypeError("请且仅请指定 filename 或 workerUrl");return me(()=>{const n=new W.Worker(t,e.workerOptions);return{postMessage:o=>n.postMessage(o),terminate:()=>n.terminate(),subscribe:(o,r)=>{const s=i=>r(new Error(`报表 Worker 在响应前退出(code ${i})`));return n.on("message",o),n.on("error",r),n.on("messageerror",r),n.on("exit",s),()=>{n.off("message",o),n.off("error",r),n.off("messageerror",r),n.off("exit",s)}}}},e)}function We(e){const t=W.parentPort;if(!t)throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");const n=o=>{ae(o)&&ce(e,o,r=>t.postMessage({protocol:E,id:o.id,type:"event",event:r})).then(r=>t.postMessage(r,fe(r)))};return t.on("message",n),()=>t.off("message",n)}function Fe(e){return j.createHash("sha256").update(e).digest("hex")}exports.ReportWorkerError=B;exports.createNodeReportExecutor=Pe;exports.openFileReportJobStore=qe;exports.reportArtifactSha256=Fe;exports.serveNodeReportWorker=We;