@agile-team/mach-report 2.7.0 → 2.8.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.
@@ -278,7 +278,27 @@ declare type MachReportLogger = Pick<Console, "warn" | "info">;
278
278
  * - 优先级:组件 props > 路由级叠加 > preset > defaults(props 永远最高)
279
279
  */
280
280
  /** 工具栏与状态文案(默认简体中文;出海场景覆写) */
281
- declare interface MachReportMessages {
281
+ declare interface MachReportMessages extends Partial<ReportCalculationMessages> {
282
+ exportMenu?: string;
283
+ exportMenuDescription?: string;
284
+ clearSearch?: string;
285
+ searchHint?: string;
286
+ searchNoMatches?: string;
287
+ pageJump?: string;
288
+ pageJumpInvalid?: string;
289
+ pageJumpHint?: string;
290
+ pagination?: string;
291
+ columnSearchHint?: string;
292
+ columnSearchShortcut?: string;
293
+ closeColumnDirectory?: string;
294
+ columnResultsMore?: string;
295
+ columnCount?: string;
296
+ settingsGeneral?: string;
297
+ settingsTools?: string;
298
+ settingsAdvanced?: string;
299
+ settingsAdvancedDescription?: string;
300
+ settingsCalculations?: string;
301
+ settingsCalculationsDescription?: string;
282
302
  title: string;
283
303
  prevPage: string;
284
304
  nextPage: string;
@@ -421,6 +441,8 @@ declare interface MachReportPreviewOptions {
421
441
  }
422
442
  /** 主题变量(组件外壳注入的 --mrp-* CSS 自定义属性) */
423
443
  declare interface MachReportTheme {
444
+ /** 空态插图强调色,不随正文颜色变灰。 */
445
+ emptyAccent?: string;
424
446
  shellBg: string;
425
447
  shellFg: string;
426
448
  toolbarBg: string;
@@ -539,6 +561,35 @@ declare interface ReportBeforeDiscardContext {
539
561
  /** Local input or a local draft, never a synonym for persisted differences. */
540
562
  pendingLocalChanges: true;
541
563
  }
564
+ declare interface ReportCalculationMessages {
565
+ calculationTitle: string;
566
+ calculationLocal: string;
567
+ calculationHint: string;
568
+ calculationFormula: string;
569
+ calculationExpression: string;
570
+ calculationExpressionHint: string;
571
+ calculationPrecision: string;
572
+ calculationRun: string;
573
+ calculationCancel: string;
574
+ calculationResult: string;
575
+ calculationIncluded: string;
576
+ calculationExcluded: string;
577
+ calculationEmpty: string;
578
+ calculationNoSelection: string;
579
+ calculationSum: string;
580
+ calculationAverage: string;
581
+ calculationMin: string;
582
+ calculationMax: string;
583
+ calculationCount: string;
584
+ calculationMedian: string;
585
+ calculationCustom: string;
586
+ calculationErrorSelection: string;
587
+ calculationErrorLimit: string;
588
+ calculationErrorExpression: string;
589
+ calculationErrorDivision: string;
590
+ calculationErrorOverflow: string;
591
+ calculationErrorPrecision: string;
592
+ }
542
593
  /** 预览中的物理坐标;合并单元格使用左上角坐标。 */
543
594
  declare interface ReportCellAddress {
544
595
  pageIndex: number;
@@ -659,6 +710,8 @@ declare interface ReportEditResult {
659
710
  /** 输出能力仍由宿主授权;工具偏好只决定当前预览实例的可见与启用状态。 */
660
711
  declare type ReportExportFormat = "html" | "pdf" | "xlsx" | "png" | "word";
661
712
  declare interface ReportInteractionOptions {
713
+ /** 只读选区计算,默认关闭;不写回业务值或执行导入的 Excel 公式。 */
714
+ calculations?: boolean;
662
715
  /** Screen-only frozen panes; exported geometry is unchanged. */
663
716
  freezeHeaders?: boolean;
664
717
  /** Leading identity columns, from 0 to 20. */
@@ -278,7 +278,27 @@ declare type MachReportLogger = Pick<Console, "warn" | "info">;
278
278
  * - 优先级:组件 props > 路由级叠加 > preset > defaults(props 永远最高)
279
279
  */
280
280
  /** 工具栏与状态文案(默认简体中文;出海场景覆写) */
281
- declare interface MachReportMessages {
281
+ declare interface MachReportMessages extends Partial<ReportCalculationMessages> {
282
+ exportMenu?: string;
283
+ exportMenuDescription?: string;
284
+ clearSearch?: string;
285
+ searchHint?: string;
286
+ searchNoMatches?: string;
287
+ pageJump?: string;
288
+ pageJumpInvalid?: string;
289
+ pageJumpHint?: string;
290
+ pagination?: string;
291
+ columnSearchHint?: string;
292
+ columnSearchShortcut?: string;
293
+ closeColumnDirectory?: string;
294
+ columnResultsMore?: string;
295
+ columnCount?: string;
296
+ settingsGeneral?: string;
297
+ settingsTools?: string;
298
+ settingsAdvanced?: string;
299
+ settingsAdvancedDescription?: string;
300
+ settingsCalculations?: string;
301
+ settingsCalculationsDescription?: string;
282
302
  title: string;
283
303
  prevPage: string;
284
304
  nextPage: string;
@@ -421,6 +441,8 @@ declare interface MachReportPreviewOptions {
421
441
  }
422
442
  /** 主题变量(组件外壳注入的 --mrp-* CSS 自定义属性) */
423
443
  declare interface MachReportTheme {
444
+ /** 空态插图强调色,不随正文颜色变灰。 */
445
+ emptyAccent?: string;
424
446
  shellBg: string;
425
447
  shellFg: string;
426
448
  toolbarBg: string;
@@ -539,6 +561,35 @@ declare interface ReportBeforeDiscardContext {
539
561
  /** Local input or a local draft, never a synonym for persisted differences. */
540
562
  pendingLocalChanges: true;
541
563
  }
564
+ declare interface ReportCalculationMessages {
565
+ calculationTitle: string;
566
+ calculationLocal: string;
567
+ calculationHint: string;
568
+ calculationFormula: string;
569
+ calculationExpression: string;
570
+ calculationExpressionHint: string;
571
+ calculationPrecision: string;
572
+ calculationRun: string;
573
+ calculationCancel: string;
574
+ calculationResult: string;
575
+ calculationIncluded: string;
576
+ calculationExcluded: string;
577
+ calculationEmpty: string;
578
+ calculationNoSelection: string;
579
+ calculationSum: string;
580
+ calculationAverage: string;
581
+ calculationMin: string;
582
+ calculationMax: string;
583
+ calculationCount: string;
584
+ calculationMedian: string;
585
+ calculationCustom: string;
586
+ calculationErrorSelection: string;
587
+ calculationErrorLimit: string;
588
+ calculationErrorExpression: string;
589
+ calculationErrorDivision: string;
590
+ calculationErrorOverflow: string;
591
+ calculationErrorPrecision: string;
592
+ }
542
593
  /** 预览中的物理坐标;合并单元格使用左上角坐标。 */
543
594
  declare interface ReportCellAddress {
544
595
  pageIndex: number;
@@ -659,6 +710,8 @@ declare interface ReportEditResult {
659
710
  /** 输出能力仍由宿主授权;工具偏好只决定当前预览实例的可见与启用状态。 */
660
711
  declare type ReportExportFormat = "html" | "pdf" | "xlsx" | "png" | "word";
661
712
  declare interface ReportInteractionOptions {
713
+ /** 只读选区计算,默认关闭;不写回业务值或执行导入的 Excel 公式。 */
714
+ calculations?: boolean;
662
715
  /** Screen-only frozen panes; exported geometry is unchanged. */
663
716
  freezeHeaders?: boolean;
664
717
  /** Leading identity columns, from 0 to 20. */
package/dist/index.cjs CHANGED
@@ -1,9 +1,9 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./render-plan-CckPEQyf.cjs"),A=require("./report-source-CCAvFE3t.cjs"),f=require("./style-CpwiOPyB.cjs"),Z=require("./validate-DfHPD8wX.cjs"),$=require("./textwrap-CnGsEum6.cjs"),H=require("./progress-KvhwXZ1Q.cjs"),j=require("./assets-RZan7EyL.cjs"),D=require("./capabilities-xGTpnPjJ.cjs"),je=require("./page-window-index-DEjnM6IB.cjs"),N=require("./template-registry-DWExx0gU.cjs"),q=require("./param-validation-CiTxFeZ8.cjs"),be=require("./number-format-CZ2T_5kF.cjs"),We={root:"mr-root",page:"mr-page",comp:"mr-comp",text:"mr-text",lines:"mr-lines",line:"mr-line",rich:"mr-rich",paragraph:"mr-paragraph",segment:"mr-segment",image:"mr-image",shape:"mr-shape",grid:"mr-grid",row:"mr-row",cell:"mr-cell",unknown:"mr-unknown"};function P(e,t){return t?.classNames?.[e]??We[e]}class qe{constructor(){this.props=[]}add(t,n){return n==null||n===!1||n===""?this:(this.props.push([t,String(n)]),this)}mm(t,n,r,o=2){return this.add(t,`${f.round(f.mmToPx(n,r),o)}px`)}toString(){let t="";for(const[n,r]of this.props)t+=`${n}:${r};`;return t}applyTo(t){const n=this.toString();n&&(t.style.cssText=n)}}function x(e,t="unset"){return new qe().add("all",t).add("display",e).add("box-sizing","border-box")}function ye(e,t,n){e.add("color",t.color).add("font-family",t.fontFamily).add("font-weight",t.bold!=null?t.bold?"700":"400":void 0).add("font-style",t.italic!=null?t.italic?"italic":"normal":void 0).add("text-decoration",t.underline!=null?t.underline?"underline":"none":void 0).add("letter-spacing",t.letterSpacing!=null?`${t.letterSpacing}pt`:void 0).add("line-height",String(f.resolveLineHeight(t))).add("text-align",t.align);const r=f.resolveFontSize(t,n);e.add("font-size",`${f.round(r.fontSizePx,2)}px`)}function Ke(e,t,n){const r=t.style??{};ye(e,r,n),e.add("background-color",r.backgroundColor).add("opacity",r.opacity!=null?String(r.opacity):void 0).add("transform",r.rotateDeg?`rotate(${r.rotateDeg}deg)`:void 0)}function Ve(e,t,n,r,o,l){const i=e.cell,a=l.createElement("td");a.className=P("cell",o),a.dataset.mrRowIndex=String(e.ri),a.dataset.mrColumnIndex=String(e.ci),a.setAttribute("role",t.table?.role==="header"?"columnheader":"cell"),i.colSpan&&(a.colSpan=i.colSpan),i.rowSpan&&(a.rowSpan=i.rowSpan);const s=f.mergeComponentStyles(t.style,i.style),c=x("block").add("position","absolute").mm("left",e.xMm,r).mm("top",e.yMm,r).mm("width",e.widthMm,r).mm("height",e.heightMm,r).add("background-color",s.backgroundColor).add("vertical-align",s.verticalAlign??"middle");ye(c,s,r),c.applyTo(a);const d=l.createElement("div");d.className="mr-cell-content",x("flex").add("position","absolute").mm("left",n,r).mm("right",n,r).mm("top",n,r).mm("bottom",n,r).add("flex-direction","column").add("justify-content",s.verticalAlign==="top"?"flex-start":s.verticalAlign==="bottom"?"flex-end":"center").add("overflow-wrap","anywhere").add("overflow","hidden").applyTo(d),i.text!=null&&d.append(i.text);for(const u of i.children??[])d.appendChild(se(u,r,o,l));return a.appendChild(d),a}function Ue(e,t,n,r){return j.resolveGridStrokes(e,t).map(o=>{const l=`${f.round(o.widthPt*n/72,2)}px solid ${o.color}`,i=r.createElement("div");i.className="mr-grid-edge",i.setAttribute("aria-hidden","true");const a=o.kind==="h";return x("block").add("position","absolute").add("pointer-events","none").mm("left",a?o.from:o.pos,n).mm("top",a?o.pos:o.from,n).mm("width",a?o.to-o.from:0,n).mm("height",a?0:o.to-o.from,n).add(a?"border-top":"border-left",l).applyTo(i),i})}function Ge(e,t,n,r,o){const l=o.createElement("table");l.className=P("grid",r),l.setAttribute("role","table"),x("block").add("position","relative").add("width","100%").add("height","100%").applyTo(l);const i=H.resolveGridLayout(e,t.widthMm,t.heightMm),a=o.createElement("tbody");x("contents").applyTo(a),l.appendChild(a);const s=e.cells.map(()=>{const d=o.createElement("tr");return d.className=P("row",r),d.setAttribute("role","row"),x("contents").applyTo(d),a.appendChild(d),d});for(const d of i.cells)s[d.ri].appendChild(Ve(d,t,e.paddingMm??.5,n,r,o));const c=o.createElement("div");return x("block").add("position","relative").add("width","100%").add("height","100%").applyTo(c),c.append(l,...Ue(i,t,n,o)),c}function Ye(e,t,n,r){const o=r.createElement("div");o.className=P("paragraph",n),x("block").add("text-align",e.align).add("line-height",e.lineHeight!=null?String(e.lineHeight):void 0).mm("margin-top",e.spaceBeforeMm??0,t).mm("margin-bottom",e.spaceAfterMm??0,t).mm("text-indent",e.indentMm??0,t).applyTo(o);for(const l of e.segments||[]){const i=r.createElement("span");i.className=P("segment",n),i.textContent=l.kind==="field"?l.field??"":l.text??"";const a=x("inline");if(l.style){const s=l.style;a.add("color",s.color).add("font-family",s.fontFamily).add("font-weight",s.bold!=null?s.bold?"700":"400":void 0).add("font-style",s.italic!=null?s.italic?"italic":"normal":void 0).add("text-decoration",s.underline!=null?s.underline?"underline":"none":void 0),(s.fontSize!=null||s.fontSizePx!=null)&&a.add("font-size",`${f.round(f.resolveFontSize(s,t).fontSizePx,2)}px`)}a.applyTo(i),o.appendChild(i)}return o}function Je(e,t,n,r){if(y.isRichText(e)){const o=r.createElement("div");o.className=P("rich",n),x("block").applyTo(o);for(const l of e.richParagraphs)o.appendChild(Ye(l,t,n,r));return o}if(Array.isArray(e.lines)&&e.lines.length>0){const o=r.createElement("div");o.className=P("lines",n),x("block").applyTo(o);for(const l of e.lines){const i=r.createElement("div");i.className=P("line",n),i.textContent=l,x("block").add("white-space","pre").add("min-height","1lh").applyTo(i),o.appendChild(i)}return o}return e.text??""}function Xe(e,t,n,r){const o=r.createElement("div");o.className=P("text",n);const l=e.style||{};return x("flex").add("width","100%").add("height","100%").add("flex-direction","column").add("justify-content",l.verticalAlign==="middle"?"center":l.verticalAlign==="bottom"?"flex-end":"flex-start").add("overflow-wrap","anywhere").add("overflow","hidden").applyTo(o),o.append(Je(e,t,n,r)),o}function Ze(e,t,n){const r=n.createElement("img");return r.className=P("image",t),r.src=e.imageData,x("block").add("width","100%").add("height","100%").add("object-fit","contain").applyTo(r),r.alt=e.kind,r}function ge(e,t,n,r){const o=r.createElement("div");o.className=P("shape",n);const l=e.style||{},i=f.resolveStroke(l),a=f.resolveBoxBorders(l),s=`${f.round(i.widthPt*t/72,2)}px solid ${i.color}`,c=x("block");return e.grid?c.add("position","relative"):e.kind==="rect"?(a.top&&c.add("border-top",s),a.right&&c.add("border-right",s),a.bottom&&c.add("border-bottom",s),a.left&&c.add("border-left",s)):e.kind==="ellipse"?(a.inner&&c.add("border",s).add("border-radius","50%"),l.backgroundColor&&c.add("background-color",l.backgroundColor)):e.kind==="line"&&c.add("height","0").add("border-top",s),c.add("box-sizing","border-box").add("width","100%").add("height","100%"),c.applyTo(o),o}function Qe(e,t,n){const r=n.createElementNS("http://www.w3.org/2000/svg","svg"),o=f.mmToPx(e.widthMm,t),l=f.mmToPx(e.heightMm,t);r.setAttribute("width",String(Math.max(1,o))),r.setAttribute("height",String(Math.max(1,l))),r.setAttribute("aria-hidden","true"),r.style.overflow="visible",r.style.display="block";const i=n.createElementNS("http://www.w3.org/2000/svg","line");i.setAttribute("x1","0"),i.setAttribute("x2",String(o)),i.setAttribute("y1",e.lineDirection==="up"?String(l):"0"),i.setAttribute("y2",e.lineDirection==="up"?"0":String(l));const a=f.resolveStroke({...e.style,borderColor:e.style?.lineColor??e.style?.borderColor});return i.setAttribute("stroke",a.color),i.setAttribute("stroke-width",String(a.widthPt*t/72)),r.appendChild(i),r}function se(e,t,n,r){const o=r.createElement("div");o.className=`${P("comp",n)} mr-kind-${e.kind}`;const l=x("block").add("position","absolute").mm("left",e.leftMm,t).mm("top",e.topMm,t).mm("width",e.widthMm,t).mm("height",e.heightMm,t).add("box-sizing","border-box");if(Ke(l,e,t),l.applyTo(o),y.isImageBackedComponent(e))return o.appendChild(Ze(e,n,r)),o;if(e.kind==="text")return o.appendChild(Xe(e,t,n,r)),o;if(e.grid){const a=ge(e,t,n,r);return a.appendChild(Ge(e.grid,e,t,n,r)),o.appendChild(a),o}if(e.kind==="line"&&e.lineDirection)return o.appendChild(Qe(e,t,r)),o;if(e.kind==="line"||e.kind==="rect"||e.kind==="ellipse")return o.appendChild(ge(e,t,n,r)),o;const i=r.createElement("div");return i.className=P("unknown",n),x("block").applyTo(i),i.textContent=e.fallbackText??`[${e.kind}]`,i.dataset.mrUnsupported=e.kind,i.setAttribute("role","note"),o.appendChild(i),o}function Me(e,t,n,r){const o=r.createElement("div");return o.className=P("page",n),x("block","initial").add("position","relative").add("font-family",y.DEFAULT_FONT_FAMILY).add("font-size",`${f.round(f.resolveFontSize(void 0,t).fontSizePx,2)}px`).add("line-height",String(f.resolveLineHeight(void 0))).add("white-space","pre-wrap").add("direction","ltr").mm("width",e.pageWidthMm,t).mm("height",e.pageHeightMm,t).add("background-color","#fff").add("color",y.DEFAULT_TEXT_COLOR).add("overflow","hidden").add("box-sizing","border-box").applyTo(o),e.components.forEach((l,i)=>{const a=se(l,t,n,r);a.dataset.mrComponentIndex=String(i),o.appendChild(a)}),o}function et(e,t,n={}){const r=n.dpi??96;D.reportOutputDiagnostics(e,"dom",n);const o=t.createElement("div");return o.className=P("root",n),x("block").applyTo(o),o.dataset.schemaVersion=e.schemaVersion,e.pages.forEach(l=>{o.appendChild(Me(l,r,n,t))}),o}function F(e){if(e?.aborted)throw e.reason??new DOMException("The operation was aborted.","AbortError")}const tt=(e,t)=>(F(t),/^data:image\/(?:png|jpe?g|webp|gif|svg\+xml)[;,]/i.test(e)?new Promise((n,r)=>{const o=new Image,l=()=>{o.onload=null,o.onerror=null,t?.removeEventListener("abort",i)},i=()=>{l(),o.src="",r(t?.reason??new DOMException("The operation was aborted.","AbortError"))};o.onload=()=>{l(),n(o)},o.onerror=()=>{l(),r(new Error("Image could not be decoded for Canvas output."))},t?.addEventListener("abort",i,{once:!0}),o.src=e}):Promise.reject(new TypeError("Canvas imageData must be an image data URL; provide imageLoader for other sources.")));function nt(e,t,n){return F(n),n?new Promise((r,o)=>{const l=()=>o(n.reason??new DOMException("The operation was aborted.","AbortError"));n.addEventListener("abort",l,{once:!0}),Promise.resolve().then(()=>e(t,n)).then(r,o).finally(()=>n.removeEventListener("abort",l))}):e(t)}async function rt(e,t,n){const r=new Map;for(const o of e.components)!y.isImageBackedComponent(o)||r.has(o.imageData)||r.set(o.imageData,await nt(t,o.imageData,n));return F(n),r}function ot(e,t,n,r,o,l){const i=t,a=i.naturalWidth??i.width??o,s=i.naturalHeight??i.height??l;if(a<=0||s<=0)throw new RangeError("Decoded Canvas image dimensions must be positive.");const c=Math.min(o/a,l/s),d=a*c,u=s*c;e.drawImage(t,n+(o-d)/2,r+(l-u)/2,d,u)}function Te(e){return je.createPageWindowIndex(e.pageHeightsPx,e.gapPx).window(e.viewportHeightPx,e.scrollTopPx,e.overscan)}const le=96/25.4;function Q(e,t=96){const n=t/96*le;return{widthPx:Math.max(1,Math.round(e.pageWidthMm*n)),heightPx:Math.max(1,Math.round(e.pageHeightMm*n))}}function xe(e,t,n,r=64e6){if(!Number.isFinite(t)||t<=0||!Number.isFinite(n)||n<=0)throw new RangeError("Canvas dpr and dpi must be positive finite numbers.");if(!Number.isFinite(r)||r<=0)throw new RangeError("maxCanvasPixels must be positive and finite.");const o=Q(e,n),l=Math.round(o.widthPx*t),i=Math.round(o.heightPx*t);if(!Number.isSafeInteger(l)||!Number.isSafeInteger(i)||l*i>r)throw new RangeError("Canvas page exceeds maxCanvasPixels; reduce resolution or split the report.");return{width:l,height:i}}function Ee(e,t,n,r){const o=document.createElement("canvas"),{widthPx:l,heightPx:i}=Q(e,n),a=xe(e,t,n,r);o.width=a.width,o.height=a.height,o.style.width=`${l}px`,o.style.height=`${i}px`;const s=o.getContext("2d");if(!s)throw new Error("当前环境不支持 Canvas 2D(测试需真浏览器,见 e2e/canvas.spec.ts)");return s.scale(t,t),s.fillStyle="#ffffff",s.fillRect(0,0,l,i),{canvas:o,ctx:s}}function it(e,t=96){return f.resolveFontSize(e,t).fontSizePx}function Se(e,t,n,r,o,l,i,a="top"){e.font=`${t.italic?"italic ":""}${t.bold?"bold ":""}${t.fontSizePx}px ${i}`,"letterSpacing"in e&&(e.letterSpacing="0px"),e.fillStyle=t.color,e.textBaseline="alphabetic";const s=t.fontSizePx*t.lineHeight,c=t.text===""?[""]:t.text.split(`
2
- `),d=c.length*s;let u=r;a==="middle"?u=r+(l-d)/2:a==="bottom"&&(u=r+l-d),c.forEach((m,h)=>{at(e,m,t,n,u+h*s+t.fontSizePx*.8,o)}),e.textAlign="left"}function at(e,t,n,r,o,l){const i=Array.from(t),a=n.letterSpacingPx??0;if(!a){e.textAlign=n.align==="center"?"center":n.align==="right"?"right":"left";const u=n.align==="center"?r+l/2:n.align==="right"?r+l:r;e.fillText(t,u,o);return}const s=e.measureText(t).width+Math.max(0,i.length-1)*a,c=n.align==="center"?r+(l-s)/2:n.align==="right"?r+l-s:r;e.textAlign="left";let d="";i.forEach((u,m)=>{e.fillText(u,c+e.measureText(d).width+m*a,o),d+=u})}function st(e,t,n,r,o,l,i){for(const a of j.resolveGridStrokes(t,n))e.strokeStyle=a.color,e.lineWidth=f.ptToPx(a.widthPt,i),e.beginPath(),a.kind==="v"?(e.moveTo(r+a.pos*l,o+a.from*l),e.lineTo(r+a.pos*l,o+a.to*l)):(e.moveTo(r+a.from*l,o+a.pos*l),e.lineTo(r+a.to*l,o+a.pos*l)),e.stroke()}function lt(e,t,n,r,o,l){e.beginPath(),t.top&&(e.moveTo(n,r),e.lineTo(n+o,r)),t.right&&(e.moveTo(n+o,r),e.lineTo(n+o,r+l)),t.bottom&&(e.moveTo(n+o,r+l),e.lineTo(n,r+l)),t.left&&(e.moveTo(n,r+l),e.lineTo(n,r)),e.stroke()}function ct(e,t,n,r,o,l,i,a,s,c,d){const u=H.resolveGridLayout(t,l/a,i/a);for(const h of u.cells){const g=h.cell.style?.backgroundColor??n.style?.backgroundColor;g&&(e.fillStyle=g,e.fillRect(r+h.xMm*a,o+h.yMm*a,h.widthMm*a,h.heightMm*a))}st(e,u,n,r,o,a,s);const m=t.paddingMm??.5;for(const h of u.cells){const g=h.cell.text??"";if(!g)continue;const p=f.mergeComponentStyles(n.style,h.cell.style),b=f.resolveFontSize(p,s),E=Math.max(0,h.widthMm-2*m),S=$.wrapText(g,E,{fontSizePt:b.fontSizePt,bold:p.bold,italic:p.italic,fontFamily:p.fontFamily??c,letterSpacingPt:p.letterSpacing},d).join(`
3
- `);Se(e,{text:S,fontSizePx:b.fontSizePx,bold:p.bold??!1,italic:p.italic,color:f.resolveTextColor(p,y.DEFAULT_TEXT_COLOR),align:p.align??"left",lineHeight:f.resolveLineHeight(p),letterSpacingPx:f.ptToPx(p.letterSpacing??0,s)},r+(h.xMm+m)*a,o+(h.yMm+m)*a,E*a,Math.max(0,h.heightMm-2*m)*a,p.fontFamily??c,p.verticalAlign??"middle")}}function dt(e,t,n,r,o,l,i,a,s){const c=t.style??{},d=f.resolveFontSize(c,i),u=y.isRichText(t)?t.richParagraphs.map(m=>m.segments.map(h=>h.text??h.field??"").join("")).join(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("./render-plan-CckPEQyf.cjs"),F=require("./report-source-CCAvFE3t.cjs"),f=require("./style-CpwiOPyB.cjs"),ne=require("./validate-DfHPD8wX.cjs"),_=require("./textwrap-CnGsEum6.cjs"),j=require("./progress-KvhwXZ1Q.cjs"),W=require("./assets-RZan7EyL.cjs"),$=require("./capabilities-xGTpnPjJ.cjs"),Je=require("./page-window-index-DEjnM6IB.cjs"),D=require("./template-registry-DWExx0gU.cjs"),V=require("./param-validation-CiTxFeZ8.cjs"),Ce=require("./number-format-CZ2T_5kF.cjs"),Xe={root:"mr-root",page:"mr-page",comp:"mr-comp",text:"mr-text",lines:"mr-lines",line:"mr-line",rich:"mr-rich",paragraph:"mr-paragraph",segment:"mr-segment",image:"mr-image",shape:"mr-shape",grid:"mr-grid",row:"mr-row",cell:"mr-cell",unknown:"mr-unknown"};function P(e,t){return t?.classNames?.[e]??Xe[e]}class Ze{constructor(){this.props=[]}add(t,n){return n==null||n===!1||n===""?this:(this.props.push([t,String(n)]),this)}mm(t,n,r,o=2){return this.add(t,`${f.round(f.mmToPx(n,r),o)}px`)}toString(){let t="";for(const[n,r]of this.props)t+=`${n}:${r};`;return t}applyTo(t){const n=this.toString();n&&(t.style.cssText=n)}}function E(e,t="unset"){return new Ze().add("all",t).add("display",e).add("box-sizing","border-box")}function Re(e,t,n){e.add("color",t.color).add("font-family",t.fontFamily).add("font-weight",t.bold!=null?t.bold?"700":"400":void 0).add("font-style",t.italic!=null?t.italic?"italic":"normal":void 0).add("text-decoration",t.underline!=null?t.underline?"underline":"none":void 0).add("letter-spacing",t.letterSpacing!=null?`${t.letterSpacing}pt`:void 0).add("line-height",String(f.resolveLineHeight(t))).add("text-align",t.align);const r=f.resolveFontSize(t,n);e.add("font-size",`${f.round(r.fontSizePx,2)}px`)}function Qe(e,t,n){const r=t.style??{};Re(e,r,n),e.add("background-color",r.backgroundColor).add("opacity",r.opacity!=null?String(r.opacity):void 0).add("transform",r.rotateDeg?`rotate(${r.rotateDeg}deg)`:void 0)}function et(e,t,n,r,o,s){const l=e.cell,i=s.createElement("td");i.className=P("cell",o),i.dataset.mrRowIndex=String(e.ri),i.dataset.mrColumnIndex=String(e.ci),i.setAttribute("role",t.table?.role==="header"?"columnheader":"cell"),l.colSpan&&(i.colSpan=l.colSpan),l.rowSpan&&(i.rowSpan=l.rowSpan);const a=f.mergeComponentStyles(t.style,l.style),c=E("block").add("position","absolute").mm("left",e.xMm,r).mm("top",e.yMm,r).mm("width",e.widthMm,r).mm("height",e.heightMm,r).add("background-color",a.backgroundColor).add("vertical-align",a.verticalAlign??"middle");Re(c,a,r),c.applyTo(i);const d=s.createElement("div");d.className="mr-cell-content",E("flex").add("position","absolute").mm("left",n,r).mm("right",n,r).mm("top",n,r).mm("bottom",n,r).add("flex-direction","column").add("justify-content",a.verticalAlign==="top"?"flex-start":a.verticalAlign==="bottom"?"flex-end":"center").add("overflow-wrap","anywhere").add("overflow","hidden").applyTo(d),l.text!=null&&d.append(l.text);for(const u of l.children??[])d.appendChild(ue(u,r,o,s));return i.appendChild(d),i}function tt(e,t,n,r){return W.resolveGridStrokes(e,t).map(o=>{const s=`${f.round(o.widthPt*n/72,2)}px solid ${o.color}`,l=r.createElement("div");l.className="mr-grid-edge",l.setAttribute("aria-hidden","true");const i=o.kind==="h";return E("block").add("position","absolute").add("pointer-events","none").mm("left",i?o.from:o.pos,n).mm("top",i?o.pos:o.from,n).mm("width",i?o.to-o.from:0,n).mm("height",i?0:o.to-o.from,n).add(i?"border-top":"border-left",s).applyTo(l),l})}function nt(e,t,n,r,o){const s=o.createElement("table");s.className=P("grid",r),s.setAttribute("role","table"),E("block").add("position","relative").add("width","100%").add("height","100%").applyTo(s);const l=j.resolveGridLayout(e,t.widthMm,t.heightMm),i=o.createElement("tbody");E("contents").applyTo(i),s.appendChild(i);const a=e.cells.map(()=>{const d=o.createElement("tr");return d.className=P("row",r),d.setAttribute("role","row"),E("contents").applyTo(d),i.appendChild(d),d});for(const d of l.cells)a[d.ri].appendChild(et(d,t,e.paddingMm??.5,n,r,o));const c=o.createElement("div");return E("block").add("position","relative").add("width","100%").add("height","100%").applyTo(c),c.append(s,...tt(l,t,n,o)),c}function rt(e,t,n,r){const o=r.createElement("div");o.className=P("paragraph",n),E("block").add("text-align",e.align).add("line-height",e.lineHeight!=null?String(e.lineHeight):void 0).mm("margin-top",e.spaceBeforeMm??0,t).mm("margin-bottom",e.spaceAfterMm??0,t).mm("text-indent",e.indentMm??0,t).applyTo(o);for(const s of e.segments||[]){const l=r.createElement("span");l.className=P("segment",n),l.textContent=s.kind==="field"?s.field??"":s.text??"";const i=E("inline");if(s.style){const a=s.style;i.add("color",a.color).add("font-family",a.fontFamily).add("font-weight",a.bold!=null?a.bold?"700":"400":void 0).add("font-style",a.italic!=null?a.italic?"italic":"normal":void 0).add("text-decoration",a.underline!=null?a.underline?"underline":"none":void 0),(a.fontSize!=null||a.fontSizePx!=null)&&i.add("font-size",`${f.round(f.resolveFontSize(a,t).fontSizePx,2)}px`)}i.applyTo(l),o.appendChild(l)}return o}function ot(e,t,n,r){if(x.isRichText(e)){const o=r.createElement("div");o.className=P("rich",n),E("block").applyTo(o);for(const s of e.richParagraphs)o.appendChild(rt(s,t,n,r));return o}if(Array.isArray(e.lines)&&e.lines.length>0){const o=r.createElement("div");o.className=P("lines",n),E("block").applyTo(o);for(const s of e.lines){const l=r.createElement("div");l.className=P("line",n),l.textContent=s,E("block").add("white-space","pre").add("min-height","1lh").applyTo(l),o.appendChild(l)}return o}return e.text??""}function it(e,t,n,r){const o=r.createElement("div");o.className=P("text",n);const s=e.style||{};return E("flex").add("width","100%").add("height","100%").add("flex-direction","column").add("justify-content",s.verticalAlign==="middle"?"center":s.verticalAlign==="bottom"?"flex-end":"flex-start").add("overflow-wrap","anywhere").add("overflow","hidden").applyTo(o),o.append(ot(e,t,n,r)),o}function at(e,t,n){const r=n.createElement("img");return r.className=P("image",t),r.src=e.imageData,E("block").add("width","100%").add("height","100%").add("object-fit","contain").applyTo(r),r.alt=e.kind,r}function ye(e,t,n,r){const o=r.createElement("div");o.className=P("shape",n);const s=e.style||{},l=f.resolveStroke(s),i=f.resolveBoxBorders(s),a=`${f.round(l.widthPt*t/72,2)}px solid ${l.color}`,c=E("block");return e.grid?c.add("position","relative"):e.kind==="rect"?(i.top&&c.add("border-top",a),i.right&&c.add("border-right",a),i.bottom&&c.add("border-bottom",a),i.left&&c.add("border-left",a)):e.kind==="ellipse"?(i.inner&&c.add("border",a).add("border-radius","50%"),s.backgroundColor&&c.add("background-color",s.backgroundColor)):e.kind==="line"&&c.add("height","0").add("border-top",a),c.add("box-sizing","border-box").add("width","100%").add("height","100%"),c.applyTo(o),o}function st(e,t,n){const r=n.createElementNS("http://www.w3.org/2000/svg","svg"),o=f.mmToPx(e.widthMm,t),s=f.mmToPx(e.heightMm,t);r.setAttribute("width",String(Math.max(1,o))),r.setAttribute("height",String(Math.max(1,s))),r.setAttribute("aria-hidden","true"),r.style.overflow="visible",r.style.display="block";const l=n.createElementNS("http://www.w3.org/2000/svg","line");l.setAttribute("x1","0"),l.setAttribute("x2",String(o)),l.setAttribute("y1",e.lineDirection==="up"?String(s):"0"),l.setAttribute("y2",e.lineDirection==="up"?"0":String(s));const i=f.resolveStroke({...e.style,borderColor:e.style?.lineColor??e.style?.borderColor});return l.setAttribute("stroke",i.color),l.setAttribute("stroke-width",String(i.widthPt*t/72)),r.appendChild(l),r}function ue(e,t,n,r){const o=r.createElement("div");o.className=`${P("comp",n)} mr-kind-${e.kind}`;const s=E("block").add("position","absolute").mm("left",e.leftMm,t).mm("top",e.topMm,t).mm("width",e.widthMm,t).mm("height",e.heightMm,t).add("box-sizing","border-box");if(Qe(s,e,t),s.applyTo(o),x.isImageBackedComponent(e))return o.appendChild(at(e,n,r)),o;if(e.kind==="text")return o.appendChild(it(e,t,n,r)),o;if(e.grid){const i=ye(e,t,n,r);return i.appendChild(nt(e.grid,e,t,n,r)),o.appendChild(i),o}if(e.kind==="line"&&e.lineDirection)return o.appendChild(st(e,t,r)),o;if(e.kind==="line"||e.kind==="rect"||e.kind==="ellipse")return o.appendChild(ye(e,t,n,r)),o;const l=r.createElement("div");return l.className=P("unknown",n),E("block").applyTo(l),l.textContent=e.fallbackText??`[${e.kind}]`,l.dataset.mrUnsupported=e.kind,l.setAttribute("role","note"),o.appendChild(l),o}function Pe(e,t,n,r){const o=r.createElement("div");return o.className=P("page",n),E("block","initial").add("position","relative").add("font-family",x.DEFAULT_FONT_FAMILY).add("font-size",`${f.round(f.resolveFontSize(void 0,t).fontSizePx,2)}px`).add("line-height",String(f.resolveLineHeight(void 0))).add("white-space","pre-wrap").add("direction","ltr").mm("width",e.pageWidthMm,t).mm("height",e.pageHeightMm,t).add("background-color","#fff").add("color",x.DEFAULT_TEXT_COLOR).add("overflow","hidden").add("box-sizing","border-box").applyTo(o),e.components.forEach((s,l)=>{const i=ue(s,t,n,r);i.dataset.mrComponentIndex=String(l),o.appendChild(i)}),o}function lt(e,t,n={}){const r=n.dpi??96;$.reportOutputDiagnostics(e,"dom",n);const o=t.createElement("div");return o.className=P("root",n),E("block").applyTo(o),o.dataset.schemaVersion=e.schemaVersion,e.pages.forEach(s=>{o.appendChild(Pe(s,r,n,t))}),o}function N(e){if(e?.aborted)throw e.reason??new DOMException("The operation was aborted.","AbortError")}const ct=(e,t)=>(N(t),/^data:image\/(?:png|jpe?g|webp|gif|svg\+xml)[;,]/i.test(e)?new Promise((n,r)=>{const o=new Image,s=()=>{o.onload=null,o.onerror=null,t?.removeEventListener("abort",l)},l=()=>{s(),o.src="",r(t?.reason??new DOMException("The operation was aborted.","AbortError"))};o.onload=()=>{s(),n(o)},o.onerror=()=>{s(),r(new Error("Image could not be decoded for Canvas output."))},t?.addEventListener("abort",l,{once:!0}),o.src=e}):Promise.reject(new TypeError("Canvas imageData must be an image data URL; provide imageLoader for other sources.")));function dt(e,t,n){return N(n),n?new Promise((r,o)=>{const s=()=>o(n.reason??new DOMException("The operation was aborted.","AbortError"));n.addEventListener("abort",s,{once:!0}),Promise.resolve().then(()=>e(t,n)).then(r,o).finally(()=>n.removeEventListener("abort",s))}):e(t)}async function ut(e,t,n){const r=new Map;for(const o of e.components)!x.isImageBackedComponent(o)||r.has(o.imageData)||r.set(o.imageData,await dt(t,o.imageData,n));return N(n),r}function mt(e,t,n,r,o,s){const l=t,i=l.naturalWidth??l.width??o,a=l.naturalHeight??l.height??s;if(i<=0||a<=0)throw new RangeError("Decoded Canvas image dimensions must be positive.");const c=Math.min(o/i,s/a),d=i*c,u=a*c;e.drawImage(t,n+(o-d)/2,r+(s-u)/2,d,u)}function Ie(e){return Je.createPageWindowIndex(e.pageHeightsPx,e.gapPx).window(e.viewportHeightPx,e.scrollTopPx,e.overscan)}const me=96/25.4;function re(e,t=96){const n=t/96*me;return{widthPx:Math.max(1,Math.round(e.pageWidthMm*n)),heightPx:Math.max(1,Math.round(e.pageHeightMm*n))}}function Ae(e,t,n,r=64e6){if(!Number.isFinite(t)||t<=0||!Number.isFinite(n)||n<=0)throw new RangeError("Canvas dpr and dpi must be positive finite numbers.");if(!Number.isFinite(r)||r<=0)throw new RangeError("maxCanvasPixels must be positive and finite.");const o=re(e,n),s=Math.round(o.widthPx*t),l=Math.round(o.heightPx*t);if(!Number.isSafeInteger(s)||!Number.isSafeInteger(l)||s*l>r)throw new RangeError("Canvas page exceeds maxCanvasPixels; reduce resolution or split the report.");return{width:s,height:l}}function ke(e,t,n,r){const o=document.createElement("canvas"),{widthPx:s,heightPx:l}=re(e,n),i=Ae(e,t,n,r);o.width=i.width,o.height=i.height,o.style.width=`${s}px`,o.style.height=`${l}px`;const a=o.getContext("2d");if(!a)throw new Error("当前环境不支持 Canvas 2D(测试需真浏览器,见 e2e/canvas.spec.ts)");return a.scale(t,t),a.fillStyle="#ffffff",a.fillRect(0,0,s,l),{canvas:o,ctx:a}}function ft(e,t=96){return f.resolveFontSize(e,t).fontSizePx}function Fe(e,t,n,r,o,s,l,i="top"){e.font=`${t.italic?"italic ":""}${t.bold?"bold ":""}${t.fontSizePx}px ${l}`,"letterSpacing"in e&&(e.letterSpacing="0px"),e.fillStyle=t.color,e.textBaseline="alphabetic";const a=t.fontSizePx*t.lineHeight,c=t.text===""?[""]:t.text.split(`
2
+ `),d=c.length*a;let u=r;i==="middle"?u=r+(s-d)/2:i==="bottom"&&(u=r+s-d),c.forEach((m,h)=>{ht(e,m,t,n,u+h*a+t.fontSizePx*.8,o)}),e.textAlign="left"}function ht(e,t,n,r,o,s){const l=Array.from(t),i=n.letterSpacingPx??0;if(!i){e.textAlign=n.align==="center"?"center":n.align==="right"?"right":"left";const u=n.align==="center"?r+s/2:n.align==="right"?r+s:r;e.fillText(t,u,o);return}const a=e.measureText(t).width+Math.max(0,l.length-1)*i,c=n.align==="center"?r+(s-a)/2:n.align==="right"?r+s-a:r;e.textAlign="left";let d="";l.forEach((u,m)=>{e.fillText(u,c+e.measureText(d).width+m*i,o),d+=u})}function gt(e,t,n,r,o,s,l){for(const i of W.resolveGridStrokes(t,n))e.strokeStyle=i.color,e.lineWidth=f.ptToPx(i.widthPt,l),e.beginPath(),i.kind==="v"?(e.moveTo(r+i.pos*s,o+i.from*s),e.lineTo(r+i.pos*s,o+i.to*s)):(e.moveTo(r+i.from*s,o+i.pos*s),e.lineTo(r+i.to*s,o+i.pos*s)),e.stroke()}function pt(e,t,n,r,o,s){e.beginPath(),t.top&&(e.moveTo(n,r),e.lineTo(n+o,r)),t.right&&(e.moveTo(n+o,r),e.lineTo(n+o,r+s)),t.bottom&&(e.moveTo(n+o,r+s),e.lineTo(n,r+s)),t.left&&(e.moveTo(n,r+s),e.lineTo(n,r)),e.stroke()}function wt(e,t,n,r,o,s,l,i,a,c,d){const u=j.resolveGridLayout(t,s/i,l/i);for(const h of u.cells){const g=h.cell.style?.backgroundColor??n.style?.backgroundColor;g&&(e.fillStyle=g,e.fillRect(r+h.xMm*i,o+h.yMm*i,h.widthMm*i,h.heightMm*i))}gt(e,u,n,r,o,i,a);const m=t.paddingMm??.5;for(const h of u.cells){const g=h.cell.text??"";if(!g)continue;const p=f.mergeComponentStyles(n.style,h.cell.style),y=f.resolveFontSize(p,a),S=Math.max(0,h.widthMm-2*m),C=_.wrapText(g,S,{fontSizePt:y.fontSizePt,bold:p.bold,italic:p.italic,fontFamily:p.fontFamily??c,letterSpacingPt:p.letterSpacing},d).join(`
3
+ `);Fe(e,{text:C,fontSizePx:y.fontSizePx,bold:p.bold??!1,italic:p.italic,color:f.resolveTextColor(p,x.DEFAULT_TEXT_COLOR),align:p.align??"left",lineHeight:f.resolveLineHeight(p),letterSpacingPx:f.ptToPx(p.letterSpacing??0,a)},r+(h.xMm+m)*i,o+(h.yMm+m)*i,S*i,Math.max(0,h.heightMm-2*m)*i,p.fontFamily??c,p.verticalAlign??"middle")}}function vt(e,t,n,r,o,s,l,i,a){const c=t.style??{},d=f.resolveFontSize(c,l),u=x.isRichText(t)?t.richParagraphs.map(m=>m.segments.map(h=>h.text??h.field??"").join("")).join(`
4
4
  `):t.lines?.length?t.lines.join(`
5
- `):$.wrapText(t.text??"",t.widthMm,{fontSizePt:d.fontSizePt,bold:c.bold,italic:c.italic,fontFamily:c.fontFamily??a,letterSpacingPt:c.letterSpacing},s).join(`
6
- `);Se(e,{text:u,fontSizePx:d.fontSizePx,bold:c.bold??!1,italic:c.italic,color:f.resolveTextColor(c),align:c.align??"left",lineHeight:f.resolveLineHeight(c),letterSpacingPx:f.ptToPx(c.letterSpacing??0,i)},n,r,o,l,c.fontFamily??a,c.verticalAlign)}function ce(e,t,n,r,o,l,i){const a=t.leftMm*n,s=t.topMm*n,c=t.widthMm*n,d=t.heightMm*n,u=t.style??{};if(y.isImageBackedComponent(t)){const m=i?.get(t.imageData);m?ot(e,m,a,s,c,d):pe(e,t,a,s,c,d);return}if(t.grid){ct(e,t.grid,t,a,s,c,d,n,r,o,l);return}switch(t.kind){case"text":{dt(e,t,a,s,c,d,r,o,l);break}case"rect":{const m=f.resolveStroke(u),h=f.resolveBoxBorders(u);u.backgroundColor&&(e.fillStyle=u.backgroundColor,e.fillRect(a,s,c,d)),h.inner&&(e.strokeStyle=m.color,e.lineWidth=f.ptToPx(m.widthPt,r),lt(e,h,a,s,c,d));break}case"line":{const m=f.resolveStroke({...u,borderColor:u.lineColor??u.borderColor});e.strokeStyle=m.color,e.lineWidth=f.ptToPx(m.widthPt,r),e.beginPath();const h=t.lineDirection==="up"?s+d:t.lineDirection==="down"?s:s+d/2,g=t.lineDirection==="up"?s:t.lineDirection==="down"?s+d:s+d/2;e.moveTo(a,h),e.lineTo(a+c,g),e.stroke();break}case"ellipse":{const m=f.resolveStroke(u);e.strokeStyle=m.color,e.lineWidth=f.ptToPx(m.widthPt,r),u.backgroundColor&&(e.fillStyle=u.backgroundColor,e.beginPath(),e.ellipse(a+c/2,s+d/2,c/2,d/2,0,0,Math.PI*2),e.fill()),e.beginPath(),e.ellipse(a+c/2,s+d/2,c/2,d/2,0,0,Math.PI*2),e.stroke();break}default:pe(e,t,a,s,c,d);break}}function pe(e,t,n,r,o,l){e.save(),e.strokeStyle="#94a3b8",e.strokeRect(n,r,o,l),e.fillStyle="#64748b",e.font="12px sans-serif",e.fillText(t.fallbackText??`[${t.kind}]`,n+3,r+14),e.restore()}async function ut(e,t={}){if(typeof document>"u")throw new Error("renderPlanToImages 需要浏览器环境(SSR/Node 请在客户端钩子中调用)");const{format:n="png",quality:r=.92,...o}=t;if(n!=="png"&&n!=="jpeg")throw new TypeError("Image format must be png or jpeg.");if(!Number.isFinite(r)||r<0||r>1)throw new RangeError("Image quality must be between 0 and 1.");F(t.signal);const l=await j.resolvePlanAssets(e,{...t,format:"canvas"});e=l.plan;const i=[...l.diagnostics,...D.reportOutputDiagnostics(e,"canvas",t)],a=n==="jpeg"?"image/jpeg":"image/png",s=[],c=Math.min(e.pages.length-1,t.end??e.pages.length-1);for(let d=Math.max(0,t.start??0);d<=c;d++){F(t.signal);const u=await Ce(e.pages[d],d,o,i);try{s.push(await mt(u,a,r,t.signal))}finally{u.width=0,u.height=0}await H.outputCheckpoint(t,s.length,c-Math.max(0,t.start??0)+1)}return F(t.signal),{blobs:s,diagnostics:i}}function mt(e,t,n,r){return F(r),new Promise((o,l)=>{const i=()=>l(r?.reason??new DOMException("The operation was aborted.","AbortError"));r?.addEventListener("abort",i,{once:!0});try{e.toBlob(a=>{r?.removeEventListener("abort",i),a?o(a):l(new Error("Canvas encoding failed; no empty image was emitted."))},t,n)}catch(a){r?.removeEventListener("abort",i),l(a)}})}function ft(e,t={}){if(F(t.signal),typeof document>"u")throw new Error("renderPlanToCanvas 需要浏览器环境(SSR 请在客户端钩子中调用)");const n=t.dpr??(typeof devicePixelRatio=="number"?devicePixelRatio:1),r=t.dpi??96,o=r/96*le,l=t.fontFamily??y.DEFAULT_FONT_FAMILY,i=t.measurer??$.heuristicMeasurer,a=Math.max(0,t.start??0),s=Math.min(e.pages.length-1,t.end??e.pages.length-1),c=[],d=D.reportOutputDiagnostics(e,"canvas",t),u=ht(e,a,s);for(const m of u)D.notifyOutputDiagnostic(m,t),d.push(m);if(t.fidelity==="strict"&&u.length)throw new D.OutputFidelityError(d);for(let m=a;m<=s;m++){F(t.signal);const h=e.pages[m],{canvas:g,ctx:p}=Ee(h,n,r,t.maxCanvasPixels);for(const b of h.components)ce(p,b,o,r,l,i);c.push(g)}return{canvases:c,diagnostics:d}}function ht(e,t,n){return n<t?[]:e.pages.slice(t,n+1).flatMap((r,o)=>r.components.flatMap((l,i)=>y.isImageBackedComponent(l)?[{code:"async-image-required",severity:"warning",format:"canvas",pageIndex:t+o,componentIndex:i,kind:l.kind,nid:l.nid,message:"Use renderPlanToCanvasAsync or renderPlanToImages to decode and include images."}]:[]))}async function gt(e,t={}){if(typeof document>"u")throw new Error("renderPlanToCanvasAsync 需要浏览器环境(Node 请使用 PDF 或 XLSX 输出)");F(t.signal);const n=await j.resolvePlanAssets(e,{...t,format:"canvas"});e=n.plan;const r=[...n.diagnostics,...D.reportOutputDiagnostics(e,"canvas",t)],o=[],l=Math.min(e.pages.length-1,t.end??e.pages.length-1);for(let i=Math.max(0,t.start??0);i<=l;i++)o.push(await Ce(e.pages[i],i,t,r));return{canvases:o,diagnostics:r}}async function Ce(e,t,n,r){const o=n.dpr??(typeof devicePixelRatio=="number"?devicePixelRatio:1),l=n.dpi??96,i=n.fontFamily??y.DEFAULT_FONT_FAMILY,a=await Pe(e,t,n,r);F(n.signal);const{canvas:s,ctx:c}=Ee(e,o,l,n.maxCanvasPixels);for(const d of e.components)ce(c,d,l/25.4,l,i,n.measurer??$.heuristicMeasurer,a);return s}async function Pe(e,t,n,r){const o=n.imageLoader??tt;return rt(e,async(l,i)=>{try{return await o(l,i)}catch(a){if(i?.aborted)throw a;const s=e.components.findIndex(u=>u.imageData===l),c=e.components[s],d={code:"image-decode-failed",severity:"warning",format:"canvas",pageIndex:t,componentIndex:s,kind:c.kind,nid:c.nid,message:"Image decoding failed; raster output was cancelled instead of omitting the image."};throw r.push(d),D.notifyOutputDiagnostic(d,n),a}},n.signal)}function pt(e,t={}){const n=t.dpr??(typeof devicePixelRatio=="number"?devicePixelRatio:1),r=t.dpi??96,o=r/96*le,l=t.fontFamily??y.DEFAULT_FONT_FAMILY,i=t.measurer??$.heuristicMeasurer,a=t.overscan??1,s=t.gapPx??18,c=t.pagesPerFrame??1,d=e.pages.map(w=>w.pageHeightMm*o),u=Math.max(1,...e.pages.map(w=>w.pageWidthMm*o)),m={start:0,end:-1};let h=null,g=null,p=null,b=null,E=[],S=0,k=[],U=0,K=new AbortController;const me=[];function _e(){const w=h;w.innerHTML="",g=document.createElement("div"),g.style.cssText=`width:${u}px;margin:0 auto;`,p=document.createElement("div"),b=document.createElement("div"),g.appendChild(p),E=[];const C=Math.min(e.pages.length,3+a*2);for(let B=0;B<C;B++){const M=document.createElement("div");M.style.cssText=`margin:0 auto ${s}px;box-shadow:0 2px 8px rgba(0,0,0,.35);background:#fff;`,g.appendChild(M),E.push(M)}g.appendChild(b),w.appendChild(g)}async function ze(w,C){const B=U,M=await j.resolvePlanAssets(e,{...t,signal:K.signal,format:"canvas",start:C,end:C});me.push(...M.diagnostics);const R=M.plan.pages[C],J=await Pe(R,C,{...t,signal:K.signal},me);if(B!==U||!h)return;const{widthPx:ie,heightPx:ae}=Q(R,r);let _=w.firstElementChild;(!_||_.tagName!=="CANVAS")&&(_=document.createElement("canvas"),w.innerHTML="",w.appendChild(_));const he=xe(R,n,r,t.maxCanvasPixels);_.width=he.width,_.height=he.height,_.style.width=`${ie}px`,_.style.height=`${ae}px`;const W=_.getContext("2d");if(W){W.setTransform(1,0,0,1,0,0),W.scale(n,n),W.fillStyle="#ffffff",W.fillRect(0,0,ie,ae);for(const He of R.components)ce(W,He,o,r,l,i,J);_.dataset.canvasPage=String(C),w.style.height=`${ae}px`,w.style.width=`${ie}px`}}function Be(w){U++,m.start=w.start,m.end=w.end,p.style.height=`${w.start*s+d.slice(0,w.start).reduce((M,R)=>M+R,0)}px`;const C=e.pages.length-1-w.end;b.style.height=`${C*s+d.slice(w.end+1).reduce((M,R)=>M+R,0)}px`;const B=w.end-w.start+1;E.forEach((M,R)=>{if(R<B){M.style.display="";const J=w.start+R;M.style.height=`${d[J]??0}px`}else M.style.display="none"}),k=[];for(let M=w.start;M<=w.end;M++){const R=E[M-w.start];if(!R)continue;R.firstElementChild?.dataset?.canvasPage!==String(M)&&k.push(M)}oe()}function oe(){S||k.length===0||(S=requestAnimationFrame(()=>{S=0;let w=Math.max(1,c);for(;k.length>0&&w-- >0;){const C=k.shift(),B=E[C-m.start];B&&ze(B,C).catch(()=>{})}k.length>0&&oe()}))}function G(){S||(S=requestAnimationFrame(()=>{S=0;const w=h,C=Te({pageHeightsPx:d,viewportHeightPx:w.clientHeight,scrollTopPx:w.scrollTop,overscan:a,gapPx:s});C.start!==m.start||C.end!==m.end?Be(C):oe()}))}let Y=null;return{attach(w){if(typeof document>"u")throw new Error("createCanvasPager 需要浏览器环境(SSR 请在客户端钩子中调用 attach)");F(t.signal),K=new AbortController,t.signal?.addEventListener("abort",fe,{once:!0}),D.reportOutputDiagnostics(e,"canvas",t),h=w,_e(),w.addEventListener("scroll",G,{passive:!0}),typeof ResizeObserver<"u"&&(Y=new ResizeObserver(()=>G()),Y.observe(w)),G()},destroy(){U++,K.abort(),t.signal?.removeEventListener("abort",fe),S&&cancelAnimationFrame(S),S=0,Y?.disconnect(),Y=null,h?.removeEventListener("scroll",G),k=[],g?.remove(),h=null},window(){return{...m}}};function fe(){K.abort(t.signal?.reason)}}function de(e,t,n){let r,o;if(typeof e=="string"){const l=f.PAPER_SIZES[e];if(!l)throw new Error(`未知纸张预设 "${e}"(可用:${Object.keys(f.PAPER_SIZES).join("/")})`);r=l.widthMm,o=l.heightMm}else typeof e=="number"?(r=e,o=t??297):(r=e.widthMm,o=e.heightMm);return n?{widthMm:o,heightMm:r}:{widthMm:r,heightMm:o}}class Re{constructor(){this.pages=[],this.pending=null,this.templateParams=void 0}params(t){return this.templateParams=t,this}page(t="a4",n={},r){this.collect();const l=r!=null&&!("margins"in r)&&!("landscape"in r)&&("marginTopMm"in r||"marginBottomMm"in r||"marginLeftMm"in r||"marginRightMm"in r)?{margins:r}:typeof n=="number"?r??{}:n,{widthMm:i,heightMm:a}=de(t,typeof n=="number"?n:void 0,l.landscape),s=l.margins??{};return this.pending=new Ie(this,{widthMm:i,heightMm:a,marginTopMm:s.marginTopMm??10,marginBottomMm:s.marginBottomMm??10,marginLeftMm:s.marginLeftMm??10,marginRightMm:s.marginRightMm??10}),this.pending}collect(){this.pending&&(this.pages.push(this.pending.buildPage()),this.pending=null)}build(){if(this.collect(),this.pages.length===0)throw new Error("模板至少需要一页:先调用 .page() 添加内容");return this.templateParams?{params:this.templateParams,pages:this.pages}:{pages:this.pages}}}class Ie{constructor(t,n){this.parent=t,this.page=n,this.components=[]}text(t,n={},r={}){return this.components.push({kind:"text",leftMm:n.leftMm??0,topMm:n.topMm??0,widthMm:n.widthMm??60,heightMm:n.heightMm??8,text:t,style:r}),this}list(t,n,r,o={}){return this.components.push({kind:"list",leftMm:n.leftMm??10,topMm:n.topMm??30,widthMm:n.widthMm??180,dataset:t,columns:r,...o}),this}rect(t,n={}){return this.components.push({kind:"rect",...t,style:n}),this}line(t,n,r,o={}){return this.components.push({kind:"line",leftMm:t,topMm:n,widthMm:r,heightMm:.5,style:o}),this}barcode(t,n){return this.components.push({kind:"barcode",leftMm:n.leftMm??0,topMm:n.topMm??0,widthMm:n.widthMm??40,heightMm:n.heightMm??12,fallbackText:t}),this}qrcode(t,n,r,o){return this.components.push({kind:"qrcode",leftMm:r,topMm:o,widthMm:n,heightMm:n,fallbackText:t}),this}buildPage(){return{...this.page,components:this.components}}done(){return this.parent}build(){return this.done().build()}}function wt(){return new Re}function vt(e,t={}){return A.validateDatasetRows([],e),e.fields.map(n=>({field:n.field,header:`${n.label??n.field}${n.unit?` (${n.unit})`:""}`,semanticRole:n.semanticRole??(n.type==="number"||n.type==="decimal"?"measure":n.type==="date"?"date":n.enum?"dimension":"text"),...t[n.field]}))}function L(e,t,n=!1){if(!Number.isFinite(e)||(n?e<0:e<=0))throw new Error(`${t} 必须是有限${n?"非负":"正"}数`)}function X(e,t,n){if(e!==void 0&&!["left","center","right","justify",...n?["auto"]:[]].includes(e))throw new Error(`${t} 必须是 left/center/right/justify${n?"/auto":""}`)}function bt(e){const t=e.layout??"page";if(t!=="page"&&t!=="wide")throw new Error("layout 必须是 page 或 wide");if(t==="wide"&&(e.paper!==void 0||e.landscape!==void 0))throw new Error('宽表布局不能同时指定 paper 或 landscape;标准纸型请使用 layout: "page"');if(t!=="wide"&&e.columnWidthMm!==void 0)throw new Error('columnWidthMm 仅适用于 layout: "wide"');const n=e.columnWidthMm??30;return L(n,"columnWidthMm"),{layout:t,columnWidthMm:n}}function yt(e){const t=e.paper===void 0?"a4":e.paper;if(typeof t!="string"&&(typeof t!="object"||t===null)||e.landscape!==void 0&&typeof e.landscape!="boolean")throw new Error("paper 必须是纸张预设名或 { widthMm, heightMm } 对象,landscape 必须是布尔值");if(typeof t=="string"&&!Object.prototype.hasOwnProperty.call(f.PAPER_SIZES,t))throw new Error(`未知纸张预设 "${t}"(可用:${Object.keys(f.PAPER_SIZES).join("/")})`);const n=de(t,void 0,e.landscape),r=n.widthMm,o=n.heightMm;return L(r,"纸张 widthMm"),L(o,"纸张 heightMm"),{widthMm:r,heightMm:o}}function Mt(e){if(e.margins!==void 0&&(!e.margins||typeof e.margins!="object"||Array.isArray(e.margins)))throw new Error("margins 必须是页边距对象");const t=e.margins??{},n={marginTopMm:t.marginTopMm===void 0?10:t.marginTopMm,marginBottomMm:t.marginBottomMm===void 0?10:t.marginBottomMm,marginLeftMm:t.marginLeftMm===void 0?10:t.marginLeftMm,marginRightMm:t.marginRightMm===void 0?10:t.marginRightMm};for(const[r,o]of Object.entries(n))L(o,r,!0);return n}function Tt(e,t){const n=e.dataset===void 0?"detail":e.dataset;if(typeof n!="string"||!n.trim())throw new Error("dataset 必须是非空字符串");if(e.title!==void 0&&typeof e.title!="string")throw new Error("title 必须是字符串");const r=e.titleHeightMm===void 0?10:e.titleHeightMm,o=e.titleGapMm===void 0?4:e.titleGapMm;L(r,"titleHeightMm"),L(o,"titleGapMm",!0);const l=e.title!==void 0&&e.title.length>0,i=l?r+o:0;if(i>=t)throw new Error("标题高度与间距占满页面,必须为表格保留可用高度");return{dataset:n,titleHeightMm:r,hasTitle:l,titleSpaceMm:i}}function xt(e){if(e.listOptions!==void 0&&(!e.listOptions||typeof e.listOptions!="object"||Array.isArray(e.listOptions)))throw new Error("listOptions 必须是列表配置对象");const t=e.listOptions??{};X(t.align,"listOptions.align",!0),X(t.headerAlign,"listOptions.headerAlign",!1);for(const n of["fontSizePt","rowHeightMm","paddingMm"]){const r=t[n];r!==void 0&&L(r,`listOptions.${n}`,n==="paddingMm")}return t}function Et(e){let t=0,n=0;for(const[r,o]of e.entries()){if(!o||typeof o.header!="string"||typeof o.field!="string"||!o.field.trim())throw new Error(`columns[${r}] 需要字符串 header 与非空 field`);X(o.align,`columns[${r}].align`,!0),X(o.headerAlign,`columns[${r}].headerAlign`,!1),o.flex!==void 0&&L(o.flex,`columns[${r}].flex`),o.widthMm!==void 0?(L(o.widthMm,`columns[${r}].widthMm`),t+=o.widthMm):n=Math.max(n,o.flex??1)}return{fixedWidthMm:t,maxFlex:n}}function St(e,t,n,r){const{fixedWidthMm:o,maxFlex:l}=Et(e.columns);if(t==="page"&&o>r)throw new Error(`固定列宽 ${o}mm 超出页面可用宽度 ${r}mm`);const i=r-o;if(t==="page"&&l>0&&i<=0)throw new Error("固定列占满页面可用宽度,自动列需要正的剩余宽度");const a=l>0?e.columns.reduce((c,d)=>c+(d.widthMm===void 0?(d.flex??1)/l:0),0):0;return{columns:e.columns.map(({widthMm:c,flex:d,...u},m)=>{const h=c??(t==="wide"?n*(d??1):i*((d??1)/l)/a);return L(h,`columns[${m}] 分配后的 widthMm`),{...u,widthMm:h}}),fixedWidthMm:o,maxFlex:l}}function Ct(e){if(!e||typeof e!="object")throw new Error("标准明细模板需要 options 对象");if(!Array.isArray(e.columns)||e.columns.length===0)throw new Error("columns 至少需要一列");const{layout:t,columnWidthMm:n}=bt(e),r=yt(e);let o=r.widthMm;const l=r.heightMm,i=Mt(e);let a=o-i.marginLeftMm-i.marginRightMm;const s=l-i.marginTopMm-i.marginBottomMm;if(t==="page"&&a<=0||s<=0)throw new Error("页边距占满纸张,必须保留正的可用宽度和高度");const{dataset:c,titleHeightMm:d,hasTitle:u,titleSpaceMm:m}=Tt(e,s),h=xt(e),{columns:g,fixedWidthMm:p,maxFlex:b}=St(e,t,n,a);t==="wide"&&(a=g.reduce((S,k)=>S+k.widthMm,0),L(a,"宽表总列宽"),o=a+i.marginLeftMm+i.marginRightMm,L(o,"宽表总宽度"));const E={widthMm:o,heightMm:l,...i,components:[],...t==="wide"?{layout:t}:{}};return u&&E.components.push({kind:"text",text:e.title,leftMm:i.marginLeftMm,topMm:i.marginTopMm,widthMm:a,heightMm:d,style:{fontSize:16,bold:!0,align:"center",verticalAlign:"middle",...e.titleStyle}}),E.components.push({align:"auto",headerAlign:"center",...h,kind:"list",...t==="wide"?{layout:t}:{},...u?{title:e.title}:{},dataset:c,columns:g,leftMm:i.marginLeftMm,topMm:i.marginTopMm+m,widthMm:t==="wide"||b>0?a:p}),e.params===void 0?{pages:[E]}:{params:e.params,pages:[E]}}function Pt(e){return e}class z extends Error{constructor(t,n){super(n),this.code=t,this.name="ReportTemplateStoreError"}}function O(e){return JSON.parse(JSON.stringify(e))}function I(e){if(!e?.aborted)return;const t=new Error("模板操作已取消");throw t.name="AbortError",t}function we(e){const t=e?Number(e.revision):0;if(!Number.isSafeInteger(t)||t<0||t>=Number.MAX_SAFE_INTEGER)throw new z("history","修订号无效或已达上限");return String(t+1)}function Rt(e,t={}){const n=async(i,a)=>{I(a);const s=await e.read(i,a);return I(a),s?O(s):void 0},r=async(i,a)=>{const s=await n(i,a.signal);if((s?.revision??null)!==a.expectedRevision)throw new z("conflict","模板已变化,请重新读取后提交");return s},o=async(i,a,s)=>{if(I(a.signal),!await e.compareAndSwap(i.id,a.expectedRevision,O(i),{signal:a.signal,...s?{publication:O(s)}:{}}))throw new z("conflict","模板已被其他请求更新");return O(i)},l=(i,a,s,c)=>{const d=we(i),u=N.parseReportTemplate({...a,revision:d}),m={revision:d,document:u,publishedAt:(t.now?.()??new Date).toISOString()};return c!==void 0&&(m.restoredFrom=c),o({id:i.id,revision:d,publishedRevision:d,published:u},s,m)};return{list:async i=>{I(i);const a=await e.list(i);return I(i),O(a)},get:async(i,a={})=>{const s=await n(i,a.signal),c=a.draft?s?.draft:s?.published;return c?N.parseReportTemplate(c):void 0},history:async(i,a)=>{I(a);const s=await e.history(i,a);return I(a),O(s)},saveDraft:async(i,a)=>{I(a.signal);const s=N.parseReportTemplate(t.migrate?await t.migrate(i):i),c=await r(s.id,a),d=we(c);return o({id:s.id,revision:d,draft:{...s,revision:d},...c?.publishedRevision?{publishedRevision:c.publishedRevision,published:c.published}:{}},a)},publish:async(i,a)=>{const s=await r(i,a);if(!s)throw new z("missing","模板不存在");if(!s.draft)throw new z("draft","没有可发布的草稿");return l(s,s.draft,a)},rollback:async(i,a,s)=>{const c=await r(i,s);if(!c)throw new z("missing","模板不存在");I(s.signal);const d=await e.getVersion(i,a,s.signal);if(!d)throw new z("history","历史修订不存在");return l(c,d.document,s,a)}}}function It(){const e=new Map,t=new Map;return{read:async(n,r)=>{I(r);const o=e.get(n);return o?O(o):void 0},list:async n=>(I(n),Array.from(e.values(),({id:r,revision:o,publishedRevision:l})=>({id:r,revision:o,...l?{publishedRevision:l}:{}}))),history:async(n,r)=>(I(r),Array.from(t.get(n)?.values()??[],o=>O(o))),getVersion:async(n,r,o)=>{I(o);const l=t.get(n)?.get(r);return l?O(l):void 0},compareAndSwap:async(n,r,o,l)=>{if(I(l.signal),(e.get(n)?.revision??null)!==r)return!1;if(o.id!==n)throw new z("history","状态 ID 与存储 ID 不一致");const i=O(o),a=l.publication;if(a){const s=t.get(n)??new Map;if(s.has(a.revision)||a.revision!==o.revision||a.document.id!==n)throw new z("history","发布修订不可覆盖,且必须与状态修订和模板 ID 一致");s.set(a.revision,O(a)),t.set(n,s)}return e.set(n,i),!0}}}function ke(e){return!e||typeof e!="object"?!1:[e.pageIndex,e.componentIndex,e.rowIndex,e.columnIndex].every(t=>Number.isInteger(t)&&t>=0)}function Ae(e,t,n){const r=e.grid;if(!r)return null;const o=r.cells[t];if(!o)return null;const i=H.resolveGridLayout(r,e.widthMm,e.heightMm).cells.filter(s=>s.ri===t).findIndex(s=>s.ci===n),a=o[i];return a?{cell:a,sourceColumnIndex:i}:null}function kt(e){return e.value!==void 0?e.value:e.rawText??e.text??null}function At(e,t){return e.valueType?e.valueType:typeof t=="number"?"number":typeof t=="boolean"?"boolean":t===null&&e.numberFormat&&/[0#?]/.test(e.numberFormat)?"number":"text"}function Ft(e,t){if(e.editable===!1)return"cell";if(e.formula!==void 0)return"formula";if(e.children?.length)return"complex";if(t.table&&t.table.role!=="body"&&e.editable!==!0)return"structure"}function Lt(e,t){const n=e.table;if(n)return{id:n.id,rowIndex:n.rowIndex+t.rowIndex,role:n.role,columnKey:n.columnKeys[t.columnIndex]}}function Ot(e,t,n){if(e.source)return{...e.source};const r=t.table?.source,o=t.table?.columnKeys[n.columnIndex];if(!(!r||r.rowKey===void 0||o===void 0))return{...r,rowKey:r.rowKey,field:o}}function Fe(e,t,n){const r=kt(n),o=Ft(n,e);return{address:{...t},cell:n,component:e,value:r,valueType:At(n,r),table:Lt(e,t),source:Ot(n,e,t),editable:o===void 0,readOnlyReason:o}}function ee(e,t){if(!ke(t))return null;const n=e.pages[t.pageIndex]?.components[t.componentIndex];if(!n)return null;const r=Ae(n,t.rowIndex,t.columnIndex);return r?Fe(n,t,r.cell):null}function te(e){const t=new Map;return n=>{if(!ke(n))return null;const r=e.pages[n.pageIndex]?.components[n.componentIndex];if(!r?.grid)return null;let o=t.get(r);if(!o){const i=new Map;o=new Map;for(const a of H.resolveGridLayout(r.grid,r.widthMm,r.heightMm).cells){const s=i.get(a.ri)??0;i.set(a.ri,s+1);const c=r.grid.cells[a.ri]?.[s];c&&o.set(`${a.ri}:${a.ci}`,c)}t.set(r,o)}const l=o.get(`${n.rowIndex}:${n.columnIndex}`);return l?Fe(r,n,l):null}}class T extends Error{constructor(t){super(`Invalid report cell edit: ${t}`),this.code=t,this.name="ReportCellEditError"}}function Dt(e,t){let n=e.trim();const r=t&&n.endsWith("%");if(r&&(n=n.slice(0,-1).trim()),/^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?(?:[eE][+-]?\d+)?$/.test(n)&&(n=n.replace(/,/g,"")),!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(n))throw new T("number");return Number(n)/(r?100:1)}function Nt(e,t){if(e===null||typeof e=="string"&&e.trim()==="")return null;if(typeof e!="string"&&typeof e!="number")throw new T("number");const n=typeof e=="number"?e:Dt(e,be.isExcelPercentageFormat(t.cell.numberFormat));if(!Number.isFinite(n)||Number.isInteger(n)&&!Number.isSafeInteger(n))throw new T("number");return n}function $t(e){if(e===null||typeof e=="string"&&e.trim()==="")return null;if(typeof e=="boolean")return e;const t=String(e).trim().toLowerCase();if(["true","yes","是","1"].includes(t))return!0;if(["false","no","否","0"].includes(t))return!1;throw new T("boolean")}function ne(e,t){return e.valueType==="number"?Nt(t,e):e.valueType==="boolean"?$t(t):t===null?null:String(t)}function _t(e,t){const n=t.cell.text,o=[["是","否"],["TRUE","FALSE"],["True","False"],["true","false"],["1","0"]].find(l=>l.includes(n??""));return o?o[e?0:1]:String(e)}function V(e,t){return t===null?"":typeof t=="boolean"?_t(t,e):typeof t=="number"?be.formatExcelNumber(t,e.cell.numberFormat):String(t)}function zt(e,t,n){const r=ee(e,t);if(!r)throw new T("missing");return ue(r,n)}function ue(e,t){if(!e.editable)throw new T("readonly");const n=ne(e,t);return{address:{...e.address},table:e.table,source:e.source,previousValue:e.value,previousText:e.cell.text??"",value:n,text:V(e,n)}}function Bt(e,t){const n=e.table,r=t.table;return!n||!r||n.columnKey===void 0?!1:n.id===r.id&&n.rowIndex===r.rowIndex&&n.role===r.role&&n.columnKey===r.columnKey}function Le(e,t,n){const r=e.grid,{rowIndex:o,columnIndex:l}=t.address,i=Ae(e,o,l),a=[...r.cells],s=[...a[o]],c=V(t,n.value),d={...i.cell,value:n.value,text:c,rawText:c};return s[i.sourceColumnIndex]=d,a[o]=s,{...e,grid:{...r,cells:a}}}function Ht(e,t){const n=e.table?.columnKeys,r=t.table?.columnKey;return n&&r!==void 0?n.flatMap((o,l)=>o===r?[l]:[]):[]}function jt(e,t,n,r,o,l){const i=t.table,a=o.table;if(!i||!a||i.id!==a.id||i.role!==a.role||!t.grid)return t;const s=a.rowIndex-i.rowIndex;if(s<0||s>=t.grid.cells.length)return t;let c=t;for(const d of Ht(t,o)){const u=ee(e,{pageIndex:n,componentIndex:r,rowIndex:s,columnIndex:d});u?.editable&&Bt(o,u)&&(c=Le(c,u,l))}return c}function Wt(e,t,n,r,o,l){const i=o.address;return o.table?.columnKey!==void 0?jt(e,t,n,r,o,l):i.pageIndex===n&&i.componentIndex===r?Le(t,o,l):t}function Oe(e,t){const n=t.source;if(!n)return!1;const r=e.source;return!r||["datasetId","rowKey","field","revision","sourceToken"].some(o=>!Object.is(r[o],n[o]))}function qt(e,t){const n=ee(e,t.address);if(!n)throw new T("missing");if(!n.editable)throw new T("readonly");if(Oe(n,t))throw new T("conflict");if(!Object.is(n.value,t.previousValue)||(n.cell.text??"")!==t.previousText)throw new T("conflict");const r=ne(n,t.value),o={...t,value:r,text:V(n,r)};if(Object.is(r,n.value)&&o.text===n.cell.text)return e;const l=e.pages.map((i,a)=>{const s=i.components.map((c,d)=>Wt(e,c,a,d,n,o));return s.every((c,d)=>c===i.components[d])?i:{...i,components:s}});return{...e,pages:l}}function Kt(e){return JSON.stringify([e.pageIndex,e.componentIndex,e.rowIndex,e.columnIndex])}function ve(e){const t=e.table;return t?.columnKey!==void 0?JSON.stringify([t.id,t.role,t.rowIndex,t.columnKey]):Kt(e.address)}function Vt(e,t){if(!t.length)return e;const n=new Map(t.map(s=>[ve(s),s])),r=new Set(t.flatMap(s=>s.table?[s.table.id]:[])),o=new Set(t.map(s=>`${s.address.pageIndex}:${s.address.componentIndex}`)),l=te(e);function i(s,c,d){const u=s.grid;if(!u||!o.has(`${c}:${d}`)&&!r.has(s.table?.id??""))return s;const m=new Map,h=new Map;for(const g of H.resolveGridLayout(u,s.widthMm,s.heightMm).cells){const p=h.get(g.ri)??0;h.set(g.ri,p+1);const b=l({pageIndex:c,componentIndex:d,rowIndex:g.ri,columnIndex:g.ci}),E=b&&n.get(ve(b));if(!E||!b.editable)continue;const S=m.get(g.ri)??[...u.cells[g.ri]],k=V(b,E.value);Object.is(b.value,E.value)&&k===b.cell.text||(S[p]={...g.cell,value:E.value,text:k,rawText:k},m.set(g.ri,S))}return m.size?{...s,grid:{...u,cells:u.cells.map((g,p)=>m.get(p)??g)}}:s}const a=e.pages.map((s,c)=>{const d=s.components.map((u,m)=>i(u,c,m));return d.every((u,m)=>u===s.components[m])?s:{...s,components:d}});return a.every((s,c)=>s===e.pages[c])?e:{...e,pages:a}}function re(e){const t=e.source;if(t)return JSON.stringify([t.datasetId,t.rowKey,t.field]);const n=e.table;if(n?.columnKey!==void 0)return JSON.stringify([n.id,n.role,n.rowIndex,n.columnKey]);const r=e.address;return JSON.stringify([r.pageIndex,r.componentIndex,r.rowIndex,r.columnIndex])}function Ut(e,t,n){if(typeof n!="string"||!n.trim()||!Array.isArray(t))throw new T("missing");if(t.length>1e4)throw new T("limit");const r=new Set,o=te(e),l=t.map(({address:i,value:a})=>{const s=o(i);if(!s)throw new T("missing");const c=ue(s,a),d=re(c);if(r.has(d))throw new T("duplicate");return r.add(d),c});return{requestId:n,edits:l}}function Gt(e,t){if(t.edits.length>1e4)throw new T("limit");const n=te(e),r=new Set,o=t.edits.map(l=>{const i=n(l.address);if(!i)throw new T("missing");const a=re(l);if(r.has(a))throw new T("duplicate");if(r.add(a),Oe(i,l)||!Object.is(i.value,l.previousValue)||(i.cell.text??"")!==l.previousText)throw new T("conflict");return ue(i,l.value)});return Vt(e,o)}function Yt(e){const t=new Map;for(const n of e){const r=re(n),o=t.get(r),l=o?{...n,previousValue:o.previousValue,previousText:o.previousText}:{...n};Object.is(l.previousValue,l.value)?t.delete(r):t.set(r,l)}return[...t.values()]}function Jt(e){return e.map(t=>t.map(n=>/[\t\r\n"]/.test(n)?`"${n.replace(/"/g,'""')}"`:n).join(" ")).join(`\r
7
- `)}function Xt(e,t){const n=e[e.length-1];e.length>1&&n?.length===1&&n[0]===""&&/[\r\n]$/.test(t)&&e.pop()}function Zt(e,t=1e4){if(e.length>4*1024*1024)throw new Error("Clipboard text limit exceeded");const n=[[]];let r="",o=!1,l=!1,i=0;function a(){if(++i>t)throw new Error("Clipboard cell limit exceeded");n[n.length-1].push(r),r="",l=!1}for(let s=0;s<e.length;s++){const c=e[s];if(o){if(c!=='"'){r+=c;continue}if(e[s+1]==='"'){r+='"',s++;continue}o=!1,l=!0;continue}if(c==='"'&&!r&&!l){o=!0;continue}if(c===" "){a();continue}if(c==="\r"||c===`
8
- `){a(),n.push([]),c==="\r"&&e[s+1]===`
9
- `&&s++;continue}if(l)throw new Error("Invalid quoted clipboard value");r+=c}if(o)throw new Error("Unclosed clipboard quote");return a(),Xt(n,e),n}function Qt(e,t,n){if(!n||n.revision===void 0&&n.sourceToken===void 0)return e;const r=new Set(t.edits.flatMap(i=>i.source?[i.source.datasetId]:[]));if(!r.size)return e;function o(i){return!i.datasetId||!r.has(i.datasetId)||(n.revision===void 0||Object.is(n.revision,i.revision))&&(n.sourceToken===void 0||n.sourceToken===i.sourceToken)?i:{...i,...n.revision!==void 0?{revision:n.revision}:{},...n.sourceToken!==void 0?{sourceToken:n.sourceToken}:{}}}const l=e.pages.map(i=>{const a=i.components.map(s=>{const c=s.table?.source?o(s.table.source):void 0,d=s.table&&c!==s.table.source?{...s.table,source:c}:s.table,u=s.grid?.cells.map(h=>{const g=h.map(p=>{if(!p?.source)return p;const b=o(p.source);return b===p.source?p:{...p,source:b}});return g.some((p,b)=>p!==h[b])?g:h}),m=s.grid&&u?.some((h,g)=>h!==s.grid.cells[g])?{...s.grid,cells:u}:s.grid;return d!==s.table||m!==s.grid?{...s,table:d,grid:m}:s});return a.some((s,c)=>s!==i.components[c])?{...i,components:a}:i});return l.some((i,a)=>i!==e.pages[a])?{...e,pages:l}:e}class De extends Error{constructor(t,n,r){const o=typeof n.label=="string"?n.label:"单元格",l={definition:`${o}的编辑器配置无效`,type:`${o}的编辑器与数据类型不一致`,required:`${o}不能为空`,min:`${o}不能小于 ${r}`,max:`${o}不能大于 ${r}`,precision:`${o}最多保留 ${r} 位小数`,length:`${o}最多允许 ${r} 个字符`,choice:`${o}请选择有效选项`,date:`${o}请输入有效日期(YYYY-MM-DD)`};super(l[t]),this.code=t,this.field=n,this.expected=r,this.name="ReportCellFieldError"}}function v(e,t,n){throw new De(t,e,n)}function Ne(e){if(typeof e!="string"||!/^\d{4}-\d{2}-\d{2}$/.test(e)||e.startsWith("0000-"))return!1;const t=new Date(`${e}T00:00:00.000Z`);return Number.isFinite(t.getTime())&&t.toISOString().slice(0,10)===e}function en(e){const[t="",n="0"]=String(e).toLowerCase().split("e");return Math.max(0,(t.split(".")[1]?.length??0)-Number(n))}function tn(e,t){e.min!==void 0&&t<e.min&&v(e,"min",e.min),e.max!==void 0&&t>e.max&&v(e,"max",e.max),e.precision!==void 0&&en(t)>e.precision&&v(e,"precision",e.precision)}function nn(e,t){Ne(t)||v(e,"date"),e.min!==void 0&&t<e.min&&v(e,"min",e.min),e.max!==void 0&&t>e.max&&v(e,"max",e.max)}function rn(e){[e.min,e.max].some(t=>t!==void 0&&!Number.isFinite(t))&&v(e,"definition"),e.min!==void 0&&e.max!==void 0&&e.min>e.max&&v(e,"definition"),e.precision!==void 0&&(!Number.isInteger(e.precision)||e.precision<0||e.precision>15)&&v(e,"definition")}function on(e){[e.min,e.max].some(t=>t!==void 0&&!Ne(t))&&v(e,"definition"),e.min!==void 0&&e.max!==void 0&&e.min>e.max&&v(e,"definition")}function an(e,t){(!Array.isArray(t.options)||!t.options.length)&&v(t,"definition");const n=e.valueType==="text"?"string":e.valueType,r=new Set;for(const o of t.options)(!o||typeof o.value!==n||typeof o.value=="number"&&!Number.isFinite(o.value))&&v(t,"definition"),o.label!==void 0&&typeof o.label!="string"&&v(t,"definition"),r.has(o.value)&&v(t,"definition"),r.add(o.value)}function sn(e){e.required!==void 0&&typeof e.required!="boolean"&&v(e,"definition"),[e.label,e.hint,e.unit].some(t=>t!==void 0&&typeof t!="string")&&v(e,"definition"),e.type==="boolean"&&[e.trueLabel,e.falseLabel].some(t=>t!==void 0&&typeof t!="string")&&v(e,"definition")}function $e(e,t){(!t||typeof t!="object"||Array.isArray(t)||!["text","number","boolean","enum","date"].includes(t.type))&&v(t??{type:"text"},"definition"),sn(t),(t.type==="number"||t.type==="boolean")&&e.valueType!==t.type&&v(t,"type"),(t.type==="text"||t.type==="date")&&e.valueType!=="text"&&v(t,"type"),t.type==="number"&&rn(t),t.type==="text"&&t.maxLength!==void 0&&(!Number.isInteger(t.maxLength)||t.maxLength<0)&&v(t,"definition"),t.type==="date"&&on(t),t.type==="enum"&&an(e,t)}function ln(e,t,n){if(!e.editable)throw new T("readonly");n&&$e(e,n);const r=ne(e,t);return n?(n.required&&typeof r=="string"&&!r.trim()&&v(n,"required"),r===null||r===""?(n.required&&v(n,"required"),r):(n.type==="number"&&tn(n,r),n.type==="date"&&nn(n,r),n.type==="text"&&n.maxLength!==void 0&&[...String(r)].length>n.maxLength&&v(n,"length",n.maxLength),n.type==="enum"&&!n.options.some(o=>Object.is(o.value,r))&&v(n,"choice"),r)):r}exports.DEFAULT_BORDER_PT=y.DEFAULT_BORDER_PT;exports.DEFAULT_FONT_FAMILY=y.DEFAULT_FONT_FAMILY;exports.DEFAULT_FONT_PT=y.DEFAULT_FONT_PT;exports.DEFAULT_STROKE_COLOR=y.DEFAULT_STROKE_COLOR;exports.DEFAULT_TEXT_COLOR=y.DEFAULT_TEXT_COLOR;exports.LINE_HEIGHT=y.LINE_HEIGHT;exports.RENDER_PLAN_SCHEMA_VERSION=y.RENDER_PLAN_SCHEMA_VERSION;exports.SCHEMA_VERSION_MACH=y.SCHEMA_VERSION_MACH;exports.isImageBackedComponent=y.isImageBackedComponent;exports.isRichText=y.isRichText;exports.PaginatePageLimitError=A.PaginatePageLimitError;exports.ReportSourceError=A.ReportSourceError;exports.createReportSource=A.createReportSource;exports.datasetJsonSchema=A.datasetJsonSchema;exports.defineReport=A.defineReport;exports.evalStyleRule=A.evalStyleRule;exports.formatValue=A.formatValue;exports.paginateTemplate=A.paginateTemplate;exports.parseDateLocal=A.parseDateLocal;exports.toExcelNumberFormat=A.toExcelNumberFormat;exports.toNumber=A.toNumber;exports.validateDatasetRows=A.validateDatasetRows;exports.CSS_DPI=f.CSS_DPI;exports.MM_PER_INCH=f.MM_PER_INCH;exports.PAPER_SIZES=f.PAPER_SIZES;exports.mergeComponentStyles=f.mergeComponentStyles;exports.mmToPx=f.mmToPx;exports.mmToPxFactor=f.mmToPxFactor;exports.ptToPx=f.ptToPx;exports.pxToMm=f.pxToMm;exports.resolveBoxBorders=f.resolveBoxBorders;exports.resolveFontSize=f.resolveFontSize;exports.resolveLineHeight=f.resolveLineHeight;exports.resolveStroke=f.resolveStroke;exports.resolveTextColor=f.resolveTextColor;exports.round=f.round;exports.assertRenderPlan=Z.assertRenderPlan;exports.validateComponent=Z.validateComponent;exports.validatePage=Z.validatePage;exports.validateRenderPlan=Z.validateRenderPlan;exports.charWidthEm=$.charWidthEm;exports.createCanvasMeasurer=$.createCanvasMeasurer;exports.createHeuristicMeasurer=$.createHeuristicMeasurer;exports.heuristicMeasurer=$.heuristicMeasurer;exports.measureTextMm=$.measureTextMm;exports.wrapText=$.wrapText;exports.resolveGridLayout=H.resolveGridLayout;exports.OutputAssetError=j.OutputAssetError;exports.resolvePlanAssets=j.resolvePlanAssets;exports.OutputFidelityError=D.OutputFidelityError;exports.inspectOutputCapabilities=D.inspectOutputCapabilities;exports.reportOutputDiagnostics=D.reportOutputDiagnostics;exports.REPORT_TEMPLATE_DOCUMENT_VERSION=N.REPORT_TEMPLATE_DOCUMENT_VERSION;exports.ReportTemplateError=N.ReportTemplateError;exports.createTemplateRegistry=N.createTemplateRegistry;exports.defineReportTemplate=N.defineReportTemplate;exports.parseReportTemplate=N.parseReportTemplate;exports.serializeReportTemplate=N.serializeReportTemplate;exports.validateReportTemplate=N.validateReportTemplate;exports.validateReportTemplateDocument=N.validateReportTemplateDocument;exports.ReportParamValidationError=q.ReportParamValidationError;exports.assertReportParams=q.assertReportParams;exports.isReportDate=q.isReportDate;exports.reportParamsJsonSchema=q.reportParamsJsonSchema;exports.validateReportParamDefinitions=q.validateReportParamDefinitions;exports.validateReportParams=q.validateReportParams;exports.PageBuilder=Ie;exports.ReportCellEditError=T;exports.ReportCellFieldError=De;exports.ReportTemplateStoreError=z;exports.TemplateBuilder=Re;exports.applyReportCellEdit=qt;exports.applyReportCellEditBatch=Gt;exports.applyReportEditResult=Qt;exports.classOf=P;exports.columnsFromContract=vt;exports.computePageWindow=Te;exports.createCanvasPager=pt;exports.createMemoryTemplateStore=It;exports.createProviderReport=Pt;exports.createReportCellEdit=zt;exports.createReportCellEditBatch=Ut;exports.createReportCellResolver=te;exports.createTableTemplate=Ct;exports.createTemplate=wt;exports.createTemplateManager=Rt;exports.formatReportCellEdit=V;exports.formatReportClipboard=Jt;exports.getReportCellContext=ee;exports.measurePageSizePx=Q;exports.parseReportCellFieldInput=ln;exports.parseReportCellInput=ne;exports.parseReportClipboard=Zt;exports.planFontSizePx=it;exports.renderComponent=se;exports.renderPage=Me;exports.renderPlan=et;exports.renderPlanToCanvas=ft;exports.renderPlanToCanvasAsync=gt;exports.renderPlanToImages=ut;exports.reportCellEditKey=re;exports.resolvePaper=de;exports.summarizeReportCellEdits=Yt;exports.validateReportCellFieldDefinition=$e;
5
+ `):_.wrapText(t.text??"",t.widthMm,{fontSizePt:d.fontSizePt,bold:c.bold,italic:c.italic,fontFamily:c.fontFamily??i,letterSpacingPt:c.letterSpacing},a).join(`
6
+ `);Fe(e,{text:u,fontSizePx:d.fontSizePx,bold:c.bold??!1,italic:c.italic,color:f.resolveTextColor(c),align:c.align??"left",lineHeight:f.resolveLineHeight(c),letterSpacingPx:f.ptToPx(c.letterSpacing??0,l)},n,r,o,s,c.fontFamily??i,c.verticalAlign)}function fe(e,t,n,r,o,s,l){const i=t.leftMm*n,a=t.topMm*n,c=t.widthMm*n,d=t.heightMm*n,u=t.style??{};if(x.isImageBackedComponent(t)){const m=l?.get(t.imageData);m?mt(e,m,i,a,c,d):xe(e,t,i,a,c,d);return}if(t.grid){wt(e,t.grid,t,i,a,c,d,n,r,o,s);return}switch(t.kind){case"text":{vt(e,t,i,a,c,d,r,o,s);break}case"rect":{const m=f.resolveStroke(u),h=f.resolveBoxBorders(u);u.backgroundColor&&(e.fillStyle=u.backgroundColor,e.fillRect(i,a,c,d)),h.inner&&(e.strokeStyle=m.color,e.lineWidth=f.ptToPx(m.widthPt,r),pt(e,h,i,a,c,d));break}case"line":{const m=f.resolveStroke({...u,borderColor:u.lineColor??u.borderColor});e.strokeStyle=m.color,e.lineWidth=f.ptToPx(m.widthPt,r),e.beginPath();const h=t.lineDirection==="up"?a+d:t.lineDirection==="down"?a:a+d/2,g=t.lineDirection==="up"?a:t.lineDirection==="down"?a+d:a+d/2;e.moveTo(i,h),e.lineTo(i+c,g),e.stroke();break}case"ellipse":{const m=f.resolveStroke(u);e.strokeStyle=m.color,e.lineWidth=f.ptToPx(m.widthPt,r),u.backgroundColor&&(e.fillStyle=u.backgroundColor,e.beginPath(),e.ellipse(i+c/2,a+d/2,c/2,d/2,0,0,Math.PI*2),e.fill()),e.beginPath(),e.ellipse(i+c/2,a+d/2,c/2,d/2,0,0,Math.PI*2),e.stroke();break}default:xe(e,t,i,a,c,d);break}}function xe(e,t,n,r,o,s){e.save(),e.strokeStyle="#94a3b8",e.strokeRect(n,r,o,s),e.fillStyle="#64748b",e.font="12px sans-serif",e.fillText(t.fallbackText??`[${t.kind}]`,n+3,r+14),e.restore()}async function bt(e,t={}){if(typeof document>"u")throw new Error("renderPlanToImages 需要浏览器环境(SSR/Node 请在客户端钩子中调用)");const{format:n="png",quality:r=.92,...o}=t;if(n!=="png"&&n!=="jpeg")throw new TypeError("Image format must be png or jpeg.");if(!Number.isFinite(r)||r<0||r>1)throw new RangeError("Image quality must be between 0 and 1.");N(t.signal);const s=await W.resolvePlanAssets(e,{...t,format:"canvas"});e=s.plan;const l=[...s.diagnostics,...$.reportOutputDiagnostics(e,"canvas",t)],i=n==="jpeg"?"image/jpeg":"image/png",a=[],c=Math.min(e.pages.length-1,t.end??e.pages.length-1);for(let d=Math.max(0,t.start??0);d<=c;d++){N(t.signal);const u=await Ne(e.pages[d],d,o,l);try{a.push(await yt(u,i,r,t.signal))}finally{u.width=0,u.height=0}await j.outputCheckpoint(t,a.length,c-Math.max(0,t.start??0)+1)}return N(t.signal),{blobs:a,diagnostics:l}}function yt(e,t,n,r){return N(r),new Promise((o,s)=>{const l=()=>s(r?.reason??new DOMException("The operation was aborted.","AbortError"));r?.addEventListener("abort",l,{once:!0});try{e.toBlob(i=>{r?.removeEventListener("abort",l),i?o(i):s(new Error("Canvas encoding failed; no empty image was emitted."))},t,n)}catch(i){r?.removeEventListener("abort",l),s(i)}})}function xt(e,t={}){if(N(t.signal),typeof document>"u")throw new Error("renderPlanToCanvas 需要浏览器环境(SSR 请在客户端钩子中调用)");const n=t.dpr??(typeof devicePixelRatio=="number"?devicePixelRatio:1),r=t.dpi??96,o=r/96*me,s=t.fontFamily??x.DEFAULT_FONT_FAMILY,l=t.measurer??_.heuristicMeasurer,i=Math.max(0,t.start??0),a=Math.min(e.pages.length-1,t.end??e.pages.length-1),c=[],d=$.reportOutputDiagnostics(e,"canvas",t),u=Mt(e,i,a);for(const m of u)$.notifyOutputDiagnostic(m,t),d.push(m);if(t.fidelity==="strict"&&u.length)throw new $.OutputFidelityError(d);for(let m=i;m<=a;m++){N(t.signal);const h=e.pages[m],{canvas:g,ctx:p}=ke(h,n,r,t.maxCanvasPixels);for(const y of h.components)fe(p,y,o,r,s,l);c.push(g)}return{canvases:c,diagnostics:d}}function Mt(e,t,n){return n<t?[]:e.pages.slice(t,n+1).flatMap((r,o)=>r.components.flatMap((s,l)=>x.isImageBackedComponent(s)?[{code:"async-image-required",severity:"warning",format:"canvas",pageIndex:t+o,componentIndex:l,kind:s.kind,nid:s.nid,message:"Use renderPlanToCanvasAsync or renderPlanToImages to decode and include images."}]:[]))}async function Tt(e,t={}){if(typeof document>"u")throw new Error("renderPlanToCanvasAsync 需要浏览器环境(Node 请使用 PDF 或 XLSX 输出)");N(t.signal);const n=await W.resolvePlanAssets(e,{...t,format:"canvas"});e=n.plan;const r=[...n.diagnostics,...$.reportOutputDiagnostics(e,"canvas",t)],o=[],s=Math.min(e.pages.length-1,t.end??e.pages.length-1);for(let l=Math.max(0,t.start??0);l<=s;l++)o.push(await Ne(e.pages[l],l,t,r));return{canvases:o,diagnostics:r}}async function Ne(e,t,n,r){const o=n.dpr??(typeof devicePixelRatio=="number"?devicePixelRatio:1),s=n.dpi??96,l=n.fontFamily??x.DEFAULT_FONT_FAMILY,i=await Le(e,t,n,r);N(n.signal);const{canvas:a,ctx:c}=ke(e,o,s,n.maxCanvasPixels);for(const d of e.components)fe(c,d,s/25.4,s,l,n.measurer??_.heuristicMeasurer,i);return a}async function Le(e,t,n,r){const o=n.imageLoader??ct;return ut(e,async(s,l)=>{try{return await o(s,l)}catch(i){if(l?.aborted)throw i;const a=e.components.findIndex(u=>u.imageData===s),c=e.components[a],d={code:"image-decode-failed",severity:"warning",format:"canvas",pageIndex:t,componentIndex:a,kind:c.kind,nid:c.nid,message:"Image decoding failed; raster output was cancelled instead of omitting the image."};throw r.push(d),$.notifyOutputDiagnostic(d,n),i}},n.signal)}function Et(e,t={}){const n=t.dpr??(typeof devicePixelRatio=="number"?devicePixelRatio:1),r=t.dpi??96,o=r/96*me,s=t.fontFamily??x.DEFAULT_FONT_FAMILY,l=t.measurer??_.heuristicMeasurer,i=t.overscan??1,a=t.gapPx??18,c=t.pagesPerFrame??1,d=e.pages.map(w=>w.pageHeightMm*o),u=Math.max(1,...e.pages.map(w=>w.pageWidthMm*o)),m={start:0,end:-1};let h=null,g=null,p=null,y=null,S=[],C=0,k=[],J=0,q=new AbortController;const we=[];function Ve(){const w=h;w.innerHTML="",g=document.createElement("div"),g.style.cssText=`width:${u}px;margin:0 auto;`,p=document.createElement("div"),y=document.createElement("div"),g.appendChild(p),S=[];const R=Math.min(e.pages.length,3+i*2);for(let B=0;B<R;B++){const M=document.createElement("div");M.style.cssText=`margin:0 auto ${a}px;box-shadow:0 2px 8px rgba(0,0,0,.35);background:#fff;`,g.appendChild(M),S.push(M)}g.appendChild(y),w.appendChild(g)}async function qe(w,R){const B=J,M=await W.resolvePlanAssets(e,{...t,signal:q.signal,format:"canvas",start:R,end:R});we.push(...M.diagnostics);const I=M.plan.pages[R],Q=await Le(I,R,{...t,signal:q.signal},we);if(B!==J||!h)return;const{widthPx:ce,heightPx:de}=re(I,r);let z=w.firstElementChild;(!z||z.tagName!=="CANVAS")&&(z=document.createElement("canvas"),w.innerHTML="",w.appendChild(z));const be=Ae(I,n,r,t.maxCanvasPixels);z.width=be.width,z.height=be.height,z.style.width=`${ce}px`,z.style.height=`${de}px`;const U=z.getContext("2d");if(U){U.setTransform(1,0,0,1,0,0),U.scale(n,n),U.fillStyle="#ffffff",U.fillRect(0,0,ce,de);for(const Ye of I.components)fe(U,Ye,o,r,s,l,Q);z.dataset.canvasPage=String(R),w.style.height=`${de}px`,w.style.width=`${ce}px`}}function Ge(w){J++,m.start=w.start,m.end=w.end,p.style.height=`${w.start*a+d.slice(0,w.start).reduce((M,I)=>M+I,0)}px`;const R=e.pages.length-1-w.end;y.style.height=`${R*a+d.slice(w.end+1).reduce((M,I)=>M+I,0)}px`;const B=w.end-w.start+1;S.forEach((M,I)=>{if(I<B){M.style.display="";const Q=w.start+I;M.style.height=`${d[Q]??0}px`}else M.style.display="none"}),k=[];for(let M=w.start;M<=w.end;M++){const I=S[M-w.start];if(!I)continue;I.firstElementChild?.dataset?.canvasPage!==String(M)&&k.push(M)}le()}function le(){C||k.length===0||(C=requestAnimationFrame(()=>{C=0;let w=Math.max(1,c);for(;k.length>0&&w-- >0;){const R=k.shift(),B=S[R-m.start];B&&qe(B,R).catch(()=>{})}k.length>0&&le()}))}function X(){C||(C=requestAnimationFrame(()=>{C=0;const w=h,R=Ie({pageHeightsPx:d,viewportHeightPx:w.clientHeight,scrollTopPx:w.scrollTop,overscan:i,gapPx:a});R.start!==m.start||R.end!==m.end?Ge(R):le()}))}let Z=null;return{attach(w){if(typeof document>"u")throw new Error("createCanvasPager 需要浏览器环境(SSR 请在客户端钩子中调用 attach)");N(t.signal),q=new AbortController,t.signal?.addEventListener("abort",ve,{once:!0}),$.reportOutputDiagnostics(e,"canvas",t),h=w,Ve(),w.addEventListener("scroll",X,{passive:!0}),typeof ResizeObserver<"u"&&(Z=new ResizeObserver(()=>X()),Z.observe(w)),X()},destroy(){J++,q.abort(),t.signal?.removeEventListener("abort",ve),C&&cancelAnimationFrame(C),C=0,Z?.disconnect(),Z=null,h?.removeEventListener("scroll",X),k=[],g?.remove(),h=null},window(){return{...m}}};function ve(){q.abort(t.signal?.reason)}}function he(e,t,n){let r,o;if(typeof e=="string"){const s=f.PAPER_SIZES[e];if(!s)throw new Error(`未知纸张预设 "${e}"(可用:${Object.keys(f.PAPER_SIZES).join("/")})`);r=s.widthMm,o=s.heightMm}else typeof e=="number"?(r=e,o=t??297):(r=e.widthMm,o=e.heightMm);return n?{widthMm:o,heightMm:r}:{widthMm:r,heightMm:o}}class Oe{constructor(){this.pages=[],this.pending=null,this.templateParams=void 0}params(t){return this.templateParams=t,this}page(t="a4",n={},r){this.collect();const s=r!=null&&!("margins"in r)&&!("landscape"in r)&&("marginTopMm"in r||"marginBottomMm"in r||"marginLeftMm"in r||"marginRightMm"in r)?{margins:r}:typeof n=="number"?r??{}:n,{widthMm:l,heightMm:i}=he(t,typeof n=="number"?n:void 0,s.landscape),a=s.margins??{};return this.pending=new $e(this,{widthMm:l,heightMm:i,marginTopMm:a.marginTopMm??10,marginBottomMm:a.marginBottomMm??10,marginLeftMm:a.marginLeftMm??10,marginRightMm:a.marginRightMm??10}),this.pending}collect(){this.pending&&(this.pages.push(this.pending.buildPage()),this.pending=null)}build(){if(this.collect(),this.pages.length===0)throw new Error("模板至少需要一页:先调用 .page() 添加内容");return this.templateParams?{params:this.templateParams,pages:this.pages}:{pages:this.pages}}}class $e{constructor(t,n){this.parent=t,this.page=n,this.components=[]}text(t,n={},r={}){return this.components.push({kind:"text",leftMm:n.leftMm??0,topMm:n.topMm??0,widthMm:n.widthMm??60,heightMm:n.heightMm??8,text:t,style:r}),this}list(t,n,r,o={}){return this.components.push({kind:"list",leftMm:n.leftMm??10,topMm:n.topMm??30,widthMm:n.widthMm??180,dataset:t,columns:r,...o}),this}rect(t,n={}){return this.components.push({kind:"rect",...t,style:n}),this}line(t,n,r,o={}){return this.components.push({kind:"line",leftMm:t,topMm:n,widthMm:r,heightMm:.5,style:o}),this}barcode(t,n){return this.components.push({kind:"barcode",leftMm:n.leftMm??0,topMm:n.topMm??0,widthMm:n.widthMm??40,heightMm:n.heightMm??12,fallbackText:t}),this}qrcode(t,n,r,o){return this.components.push({kind:"qrcode",leftMm:r,topMm:o,widthMm:n,heightMm:n,fallbackText:t}),this}buildPage(){return{...this.page,components:this.components}}done(){return this.parent}build(){return this.done().build()}}function St(){return new Oe}function Ct(e,t={}){return F.validateDatasetRows([],e),e.fields.map(n=>({field:n.field,header:`${n.label??n.field}${n.unit?` (${n.unit})`:""}`,semanticRole:n.semanticRole??(n.type==="number"||n.type==="decimal"?"measure":n.type==="date"?"date":n.enum?"dimension":"text"),...t[n.field]}))}function L(e,t,n=!1){if(!Number.isFinite(e)||(n?e<0:e<=0))throw new Error(`${t} 必须是有限${n?"非负":"正"}数`)}function ee(e,t,n){if(e!==void 0&&!["left","center","right","justify",...n?["auto"]:[]].includes(e))throw new Error(`${t} 必须是 left/center/right/justify${n?"/auto":""}`)}function Rt(e){const t=e.layout??"page";if(t!=="page"&&t!=="wide")throw new Error("layout 必须是 page 或 wide");if(t==="wide"&&(e.paper!==void 0||e.landscape!==void 0))throw new Error('宽表布局不能同时指定 paper 或 landscape;标准纸型请使用 layout: "page"');if(t!=="wide"&&e.columnWidthMm!==void 0)throw new Error('columnWidthMm 仅适用于 layout: "wide"');const n=e.columnWidthMm??30;return L(n,"columnWidthMm"),{layout:t,columnWidthMm:n}}function Pt(e){const t=e.paper===void 0?"a4":e.paper;if(typeof t!="string"&&(typeof t!="object"||t===null)||e.landscape!==void 0&&typeof e.landscape!="boolean")throw new Error("paper 必须是纸张预设名或 { widthMm, heightMm } 对象,landscape 必须是布尔值");if(typeof t=="string"&&!Object.prototype.hasOwnProperty.call(f.PAPER_SIZES,t))throw new Error(`未知纸张预设 "${t}"(可用:${Object.keys(f.PAPER_SIZES).join("/")})`);const n=he(t,void 0,e.landscape),r=n.widthMm,o=n.heightMm;return L(r,"纸张 widthMm"),L(o,"纸张 heightMm"),{widthMm:r,heightMm:o}}function It(e){if(e.margins!==void 0&&(!e.margins||typeof e.margins!="object"||Array.isArray(e.margins)))throw new Error("margins 必须是页边距对象");const t=e.margins??{},n={marginTopMm:t.marginTopMm===void 0?10:t.marginTopMm,marginBottomMm:t.marginBottomMm===void 0?10:t.marginBottomMm,marginLeftMm:t.marginLeftMm===void 0?10:t.marginLeftMm,marginRightMm:t.marginRightMm===void 0?10:t.marginRightMm};for(const[r,o]of Object.entries(n))L(o,r,!0);return n}function At(e,t){const n=e.dataset===void 0?"detail":e.dataset;if(typeof n!="string"||!n.trim())throw new Error("dataset 必须是非空字符串");if(e.title!==void 0&&typeof e.title!="string")throw new Error("title 必须是字符串");const r=e.titleHeightMm===void 0?10:e.titleHeightMm,o=e.titleGapMm===void 0?4:e.titleGapMm;L(r,"titleHeightMm"),L(o,"titleGapMm",!0);const s=e.title!==void 0&&e.title.length>0,l=s?r+o:0;if(l>=t)throw new Error("标题高度与间距占满页面,必须为表格保留可用高度");return{dataset:n,titleHeightMm:r,hasTitle:s,titleSpaceMm:l}}function kt(e){if(e.listOptions!==void 0&&(!e.listOptions||typeof e.listOptions!="object"||Array.isArray(e.listOptions)))throw new Error("listOptions 必须是列表配置对象");const t=e.listOptions??{};ee(t.align,"listOptions.align",!0),ee(t.headerAlign,"listOptions.headerAlign",!1);for(const n of["fontSizePt","rowHeightMm","paddingMm"]){const r=t[n];r!==void 0&&L(r,`listOptions.${n}`,n==="paddingMm")}return t}function Ft(e){let t=0,n=0;for(const[r,o]of e.entries()){if(!o||typeof o.header!="string"||typeof o.field!="string"||!o.field.trim())throw new Error(`columns[${r}] 需要字符串 header 与非空 field`);ee(o.align,`columns[${r}].align`,!0),ee(o.headerAlign,`columns[${r}].headerAlign`,!1),o.flex!==void 0&&L(o.flex,`columns[${r}].flex`),o.widthMm!==void 0?(L(o.widthMm,`columns[${r}].widthMm`),t+=o.widthMm):n=Math.max(n,o.flex??1)}return{fixedWidthMm:t,maxFlex:n}}function Nt(e,t,n,r){const{fixedWidthMm:o,maxFlex:s}=Ft(e.columns);if(t==="page"&&o>r)throw new Error(`固定列宽 ${o}mm 超出页面可用宽度 ${r}mm`);const l=r-o;if(t==="page"&&s>0&&l<=0)throw new Error("固定列占满页面可用宽度,自动列需要正的剩余宽度");const i=s>0?e.columns.reduce((c,d)=>c+(d.widthMm===void 0?(d.flex??1)/s:0),0):0;return{columns:e.columns.map(({widthMm:c,flex:d,...u},m)=>{const h=c??(t==="wide"?n*(d??1):l*((d??1)/s)/i);return L(h,`columns[${m}] 分配后的 widthMm`),{...u,widthMm:h}}),fixedWidthMm:o,maxFlex:s}}function Lt(e){if(!e||typeof e!="object")throw new Error("标准明细模板需要 options 对象");if(!Array.isArray(e.columns)||e.columns.length===0)throw new Error("columns 至少需要一列");const{layout:t,columnWidthMm:n}=Rt(e),r=Pt(e);let o=r.widthMm;const s=r.heightMm,l=It(e);let i=o-l.marginLeftMm-l.marginRightMm;const a=s-l.marginTopMm-l.marginBottomMm;if(t==="page"&&i<=0||a<=0)throw new Error("页边距占满纸张,必须保留正的可用宽度和高度");const{dataset:c,titleHeightMm:d,hasTitle:u,titleSpaceMm:m}=At(e,a),h=kt(e),{columns:g,fixedWidthMm:p,maxFlex:y}=Nt(e,t,n,i);t==="wide"&&(i=g.reduce((C,k)=>C+k.widthMm,0),L(i,"宽表总列宽"),o=i+l.marginLeftMm+l.marginRightMm,L(o,"宽表总宽度"));const S={widthMm:o,heightMm:s,...l,components:[],...t==="wide"?{layout:t}:{}};return u&&S.components.push({kind:"text",text:e.title,leftMm:l.marginLeftMm,topMm:l.marginTopMm,widthMm:i,heightMm:d,style:{fontSize:16,bold:!0,align:"center",verticalAlign:"middle",...e.titleStyle}}),S.components.push({align:"auto",headerAlign:"center",...h,kind:"list",...t==="wide"?{layout:t}:{},...u?{title:e.title}:{},dataset:c,columns:g,leftMm:l.marginLeftMm,topMm:l.marginTopMm+m,widthMm:t==="wide"||y>0?i:p}),e.params===void 0?{pages:[S]}:{params:e.params,pages:[S]}}function Ot(e){return e}class H extends Error{constructor(t,n){super(n),this.code=t,this.name="ReportTemplateStoreError"}}function O(e){return JSON.parse(JSON.stringify(e))}function A(e){if(!e?.aborted)return;const t=new Error("模板操作已取消");throw t.name="AbortError",t}function Me(e){const t=e?Number(e.revision):0;if(!Number.isSafeInteger(t)||t<0||t>=Number.MAX_SAFE_INTEGER)throw new H("history","修订号无效或已达上限");return String(t+1)}function $t(e,t={}){const n=async(l,i)=>{A(i);const a=await e.read(l,i);return A(i),a?O(a):void 0},r=async(l,i)=>{const a=await n(l,i.signal);if((a?.revision??null)!==i.expectedRevision)throw new H("conflict","模板已变化,请重新读取后提交");return a},o=async(l,i,a)=>{if(A(i.signal),!await e.compareAndSwap(l.id,i.expectedRevision,O(l),{signal:i.signal,...a?{publication:O(a)}:{}}))throw new H("conflict","模板已被其他请求更新");return O(l)},s=(l,i,a,c)=>{const d=Me(l),u=D.parseReportTemplate({...i,revision:d}),m={revision:d,document:u,publishedAt:(t.now?.()??new Date).toISOString()};return c!==void 0&&(m.restoredFrom=c),o({id:l.id,revision:d,publishedRevision:d,published:u},a,m)};return{list:async l=>{A(l);const i=await e.list(l);return A(l),O(i)},get:async(l,i={})=>{const a=await n(l,i.signal),c=i.draft?a?.draft:a?.published;return c?D.parseReportTemplate(c):void 0},history:async(l,i)=>{A(i);const a=await e.history(l,i);return A(i),O(a)},saveDraft:async(l,i)=>{A(i.signal);const a=D.parseReportTemplate(t.migrate?await t.migrate(l):l),c=await r(a.id,i),d=Me(c);return o({id:a.id,revision:d,draft:{...a,revision:d},...c?.publishedRevision?{publishedRevision:c.publishedRevision,published:c.published}:{}},i)},publish:async(l,i)=>{const a=await r(l,i);if(!a)throw new H("missing","模板不存在");if(!a.draft)throw new H("draft","没有可发布的草稿");return s(a,a.draft,i)},rollback:async(l,i,a)=>{const c=await r(l,a);if(!c)throw new H("missing","模板不存在");A(a.signal);const d=await e.getVersion(l,i,a.signal);if(!d)throw new H("history","历史修订不存在");return s(c,d.document,a,i)}}}function Dt(){const e=new Map,t=new Map;return{read:async(n,r)=>{A(r);const o=e.get(n);return o?O(o):void 0},list:async n=>(A(n),Array.from(e.values(),({id:r,revision:o,publishedRevision:s})=>({id:r,revision:o,...s?{publishedRevision:s}:{}}))),history:async(n,r)=>(A(r),Array.from(t.get(n)?.values()??[],o=>O(o))),getVersion:async(n,r,o)=>{A(o);const s=t.get(n)?.get(r);return s?O(s):void 0},compareAndSwap:async(n,r,o,s)=>{if(A(s.signal),(e.get(n)?.revision??null)!==r)return!1;if(o.id!==n)throw new H("history","状态 ID 与存储 ID 不一致");const l=O(o),i=s.publication;if(i){const a=t.get(n)??new Map;if(a.has(i.revision)||i.revision!==o.revision||i.document.id!==n)throw new H("history","发布修订不可覆盖,且必须与状态修订和模板 ID 一致");a.set(i.revision,O(i)),t.set(n,a)}return e.set(n,l),!0}}}function De(e){return!e||typeof e!="object"?!1:[e.pageIndex,e.componentIndex,e.rowIndex,e.columnIndex].every(t=>Number.isInteger(t)&&t>=0)}function _e(e,t,n){const r=e.grid;if(!r)return null;const o=r.cells[t];if(!o)return null;const l=j.resolveGridLayout(r,e.widthMm,e.heightMm).cells.filter(a=>a.ri===t).findIndex(a=>a.ci===n),i=o[l];return i?{cell:i,sourceColumnIndex:l}:null}function _t(e){return e.value!==void 0?e.value:e.rawText??e.text??null}function zt(e,t){return e.valueType?e.valueType:typeof t=="number"?"number":typeof t=="boolean"?"boolean":t===null&&e.numberFormat&&/[0#?]/.test(e.numberFormat)?"number":"text"}function Ht(e,t){if(e.editable===!1)return"cell";if(e.formula!==void 0)return"formula";if(e.children?.length)return"complex";if(t.table&&t.table.role!=="body"&&e.editable!==!0)return"structure"}function Bt(e,t){const n=e.table;if(n)return{id:n.id,rowIndex:n.rowIndex+t.rowIndex,role:n.role,columnKey:n.columnKeys[t.columnIndex]}}function jt(e,t,n){if(e.source)return{...e.source};const r=t.table?.source,o=t.table?.columnKeys[n.columnIndex];if(!(!r||r.rowKey===void 0||o===void 0))return{...r,rowKey:r.rowKey,field:o}}function ze(e,t,n){const r=_t(n),o=Ht(n,e);return{address:{...t},cell:n,component:e,value:r,valueType:zt(n,r),table:Bt(e,t),source:jt(n,e,t),editable:o===void 0,readOnlyReason:o}}function oe(e,t){if(!De(t))return null;const n=e.pages[t.pageIndex]?.components[t.componentIndex];if(!n)return null;const r=_e(n,t.rowIndex,t.columnIndex);return r?ze(n,t,r.cell):null}function ie(e){const t=new Map;return n=>{if(!De(n))return null;const r=e.pages[n.pageIndex]?.components[n.componentIndex];if(!r?.grid)return null;let o=t.get(r);if(!o){const l=new Map;o=new Map;for(const i of j.resolveGridLayout(r.grid,r.widthMm,r.heightMm).cells){const a=l.get(i.ri)??0;l.set(i.ri,a+1);const c=r.grid.cells[i.ri]?.[a];c&&o.set(`${i.ri}:${i.ci}`,c)}t.set(r,o)}const s=o.get(`${n.rowIndex}:${n.columnIndex}`);return s?ze(r,n,s):null}}class T extends Error{constructor(t){super(`Invalid report cell edit: ${t}`),this.code=t,this.name="ReportCellEditError"}}function Wt(e,t){let n=e.trim();const r=t&&n.endsWith("%");if(r&&(n=n.slice(0,-1).trim()),/^[+-]?\d{1,3}(?:,\d{3})+(?:\.\d*)?(?:[eE][+-]?\d+)?$/.test(n)&&(n=n.replace(/,/g,"")),!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(n))throw new T("number");return Number(n)/(r?100:1)}function Ut(e,t){if(e===null||typeof e=="string"&&e.trim()==="")return null;if(typeof e!="string"&&typeof e!="number")throw new T("number");const n=typeof e=="number"?e:Wt(e,Ce.isExcelPercentageFormat(t.cell.numberFormat));if(!Number.isFinite(n)||Number.isInteger(n)&&!Number.isSafeInteger(n))throw new T("number");return n}function Kt(e){if(e===null||typeof e=="string"&&e.trim()==="")return null;if(typeof e=="boolean")return e;const t=String(e).trim().toLowerCase();if(["true","yes","是","1"].includes(t))return!0;if(["false","no","否","0"].includes(t))return!1;throw new T("boolean")}function ae(e,t){return e.valueType==="number"?Ut(t,e):e.valueType==="boolean"?Kt(t):t===null?null:String(t)}function Vt(e,t){const n=t.cell.text,o=[["是","否"],["TRUE","FALSE"],["True","False"],["true","false"],["1","0"]].find(s=>s.includes(n??""));return o?o[e?0:1]:String(e)}function Y(e,t){return t===null?"":typeof t=="boolean"?Vt(t,e):typeof t=="number"?Ce.formatExcelNumber(t,e.cell.numberFormat):String(t)}function qt(e,t,n){const r=oe(e,t);if(!r)throw new T("missing");return ge(r,n)}function ge(e,t){if(!e.editable)throw new T("readonly");const n=ae(e,t);return{address:{...e.address},table:e.table,source:e.source,previousValue:e.value,previousText:e.cell.text??"",value:n,text:Y(e,n)}}function Gt(e,t){const n=e.table,r=t.table;return!n||!r||n.columnKey===void 0?!1:n.id===r.id&&n.rowIndex===r.rowIndex&&n.role===r.role&&n.columnKey===r.columnKey}function He(e,t,n){const r=e.grid,{rowIndex:o,columnIndex:s}=t.address,l=_e(e,o,s),i=[...r.cells],a=[...i[o]],c=Y(t,n.value),d={...l.cell,value:n.value,text:c,rawText:c};return a[l.sourceColumnIndex]=d,i[o]=a,{...e,grid:{...r,cells:i}}}function Yt(e,t){const n=e.table?.columnKeys,r=t.table?.columnKey;return n&&r!==void 0?n.flatMap((o,s)=>o===r?[s]:[]):[]}function Jt(e,t,n,r,o,s){const l=t.table,i=o.table;if(!l||!i||l.id!==i.id||l.role!==i.role||!t.grid)return t;const a=i.rowIndex-l.rowIndex;if(a<0||a>=t.grid.cells.length)return t;let c=t;for(const d of Yt(t,o)){const u=oe(e,{pageIndex:n,componentIndex:r,rowIndex:a,columnIndex:d});u?.editable&&Gt(o,u)&&(c=He(c,u,s))}return c}function Xt(e,t,n,r,o,s){const l=o.address;return o.table?.columnKey!==void 0?Jt(e,t,n,r,o,s):l.pageIndex===n&&l.componentIndex===r?He(t,o,s):t}function Be(e,t){const n=t.source;if(!n)return!1;const r=e.source;return!r||["datasetId","rowKey","field","revision","sourceToken"].some(o=>!Object.is(r[o],n[o]))}function Zt(e,t){const n=oe(e,t.address);if(!n)throw new T("missing");if(!n.editable)throw new T("readonly");if(Be(n,t))throw new T("conflict");if(!Object.is(n.value,t.previousValue)||(n.cell.text??"")!==t.previousText)throw new T("conflict");const r=ae(n,t.value),o={...t,value:r,text:Y(n,r)};if(Object.is(r,n.value)&&o.text===n.cell.text)return e;const s=e.pages.map((l,i)=>{const a=l.components.map((c,d)=>Xt(e,c,i,d,n,o));return a.every((c,d)=>c===l.components[d])?l:{...l,components:a}});return{...e,pages:s}}function Qt(e){return JSON.stringify([e.pageIndex,e.componentIndex,e.rowIndex,e.columnIndex])}function Te(e){const t=e.table;return t?.columnKey!==void 0?JSON.stringify([t.id,t.role,t.rowIndex,t.columnKey]):Qt(e.address)}function en(e,t){if(!t.length)return e;const n=new Map(t.map(a=>[Te(a),a])),r=new Set(t.flatMap(a=>a.table?[a.table.id]:[])),o=new Set(t.map(a=>`${a.address.pageIndex}:${a.address.componentIndex}`)),s=ie(e);function l(a,c,d){const u=a.grid;if(!u||!o.has(`${c}:${d}`)&&!r.has(a.table?.id??""))return a;const m=new Map,h=new Map;for(const g of j.resolveGridLayout(u,a.widthMm,a.heightMm).cells){const p=h.get(g.ri)??0;h.set(g.ri,p+1);const y=s({pageIndex:c,componentIndex:d,rowIndex:g.ri,columnIndex:g.ci}),S=y&&n.get(Te(y));if(!S||!y.editable)continue;const C=m.get(g.ri)??[...u.cells[g.ri]],k=Y(y,S.value);Object.is(y.value,S.value)&&k===y.cell.text||(C[p]={...g.cell,value:S.value,text:k,rawText:k},m.set(g.ri,C))}return m.size?{...a,grid:{...u,cells:u.cells.map((g,p)=>m.get(p)??g)}}:a}const i=e.pages.map((a,c)=>{const d=a.components.map((u,m)=>l(u,c,m));return d.every((u,m)=>u===a.components[m])?a:{...a,components:d}});return i.every((a,c)=>a===e.pages[c])?e:{...e,pages:i}}function se(e){const t=e.source;if(t)return JSON.stringify([t.datasetId,t.rowKey,t.field]);const n=e.table;if(n?.columnKey!==void 0)return JSON.stringify([n.id,n.role,n.rowIndex,n.columnKey]);const r=e.address;return JSON.stringify([r.pageIndex,r.componentIndex,r.rowIndex,r.columnIndex])}function tn(e,t,n){if(typeof n!="string"||!n.trim()||!Array.isArray(t))throw new T("missing");if(t.length>1e4)throw new T("limit");const r=new Set,o=ie(e),s=t.map(({address:l,value:i})=>{const a=o(l);if(!a)throw new T("missing");const c=ge(a,i),d=se(c);if(r.has(d))throw new T("duplicate");return r.add(d),c});return{requestId:n,edits:s}}function nn(e,t){if(t.edits.length>1e4)throw new T("limit");const n=ie(e),r=new Set,o=t.edits.map(s=>{const l=n(s.address);if(!l)throw new T("missing");const i=se(s);if(r.has(i))throw new T("duplicate");if(r.add(i),Be(l,s)||!Object.is(l.value,s.previousValue)||(l.cell.text??"")!==s.previousText)throw new T("conflict");return ge(l,s.value)});return en(e,o)}function rn(e){const t=new Map;for(const n of e){const r=se(n),o=t.get(r),s=o?{...n,previousValue:o.previousValue,previousText:o.previousText}:{...n};Object.is(s.previousValue,s.value)?t.delete(r):t.set(r,s)}return[...t.values()]}function on(e){return e.map(t=>t.map(n=>/[\t\r\n"]/.test(n)?`"${n.replace(/"/g,'""')}"`:n).join(" ")).join(`\r
7
+ `)}function an(e,t){const n=e[e.length-1];e.length>1&&n?.length===1&&n[0]===""&&/[\r\n]$/.test(t)&&e.pop()}function sn(e,t=1e4){if(e.length>4*1024*1024)throw new Error("Clipboard text limit exceeded");const n=[[]];let r="",o=!1,s=!1,l=0;function i(){if(++l>t)throw new Error("Clipboard cell limit exceeded");n[n.length-1].push(r),r="",s=!1}for(let a=0;a<e.length;a++){const c=e[a];if(o){if(c!=='"'){r+=c;continue}if(e[a+1]==='"'){r+='"',a++;continue}o=!1,s=!0;continue}if(c==='"'&&!r&&!s){o=!0;continue}if(c===" "){i();continue}if(c==="\r"||c===`
8
+ `){i(),n.push([]),c==="\r"&&e[a+1]===`
9
+ `&&a++;continue}if(s)throw new Error("Invalid quoted clipboard value");r+=c}if(o)throw new Error("Unclosed clipboard quote");return i(),an(n,e),n}function ln(e,t,n){if(!n||n.revision===void 0&&n.sourceToken===void 0)return e;const r=new Set(t.edits.flatMap(l=>l.source?[l.source.datasetId]:[]));if(!r.size)return e;function o(l){return!l.datasetId||!r.has(l.datasetId)||(n.revision===void 0||Object.is(n.revision,l.revision))&&(n.sourceToken===void 0||n.sourceToken===l.sourceToken)?l:{...l,...n.revision!==void 0?{revision:n.revision}:{},...n.sourceToken!==void 0?{sourceToken:n.sourceToken}:{}}}const s=e.pages.map(l=>{const i=l.components.map(a=>{const c=a.table?.source?o(a.table.source):void 0,d=a.table&&c!==a.table.source?{...a.table,source:c}:a.table,u=a.grid?.cells.map(h=>{const g=h.map(p=>{if(!p?.source)return p;const y=o(p.source);return y===p.source?p:{...p,source:y}});return g.some((p,y)=>p!==h[y])?g:h}),m=a.grid&&u?.some((h,g)=>h!==a.grid.cells[g])?{...a.grid,cells:u}:a.grid;return d!==a.table||m!==a.grid?{...a,table:d,grid:m}:a});return i.some((a,c)=>a!==l.components[c])?{...l,components:i}:l});return s.some((l,i)=>l!==e.pages[i])?{...e,pages:s}:e}class je extends Error{constructor(t,n,r){const o=typeof n.label=="string"?n.label:"单元格",s={definition:`${o}的编辑器配置无效`,type:`${o}的编辑器与数据类型不一致`,required:`${o}不能为空`,min:`${o}不能小于 ${r}`,max:`${o}不能大于 ${r}`,precision:`${o}最多保留 ${r} 位小数`,length:`${o}最多允许 ${r} 个字符`,choice:`${o}请选择有效选项`,date:`${o}请输入有效日期(YYYY-MM-DD)`};super(s[t]),this.code=t,this.field=n,this.expected=r,this.name="ReportCellFieldError"}}function v(e,t,n){throw new je(t,e,n)}function We(e){if(typeof e!="string"||!/^\d{4}-\d{2}-\d{2}$/.test(e)||e.startsWith("0000-"))return!1;const t=new Date(`${e}T00:00:00.000Z`);return Number.isFinite(t.getTime())&&t.toISOString().slice(0,10)===e}function cn(e){const[t="",n="0"]=String(e).toLowerCase().split("e");return Math.max(0,(t.split(".")[1]?.length??0)-Number(n))}function dn(e,t){e.min!==void 0&&t<e.min&&v(e,"min",e.min),e.max!==void 0&&t>e.max&&v(e,"max",e.max),e.precision!==void 0&&cn(t)>e.precision&&v(e,"precision",e.precision)}function un(e,t){We(t)||v(e,"date"),e.min!==void 0&&t<e.min&&v(e,"min",e.min),e.max!==void 0&&t>e.max&&v(e,"max",e.max)}function mn(e){[e.min,e.max].some(t=>t!==void 0&&!Number.isFinite(t))&&v(e,"definition"),e.min!==void 0&&e.max!==void 0&&e.min>e.max&&v(e,"definition"),e.precision!==void 0&&(!Number.isInteger(e.precision)||e.precision<0||e.precision>15)&&v(e,"definition")}function fn(e){[e.min,e.max].some(t=>t!==void 0&&!We(t))&&v(e,"definition"),e.min!==void 0&&e.max!==void 0&&e.min>e.max&&v(e,"definition")}function hn(e,t){(!Array.isArray(t.options)||!t.options.length)&&v(t,"definition");const n=e.valueType==="text"?"string":e.valueType,r=new Set;for(const o of t.options)(!o||typeof o.value!==n||typeof o.value=="number"&&!Number.isFinite(o.value))&&v(t,"definition"),o.label!==void 0&&typeof o.label!="string"&&v(t,"definition"),r.has(o.value)&&v(t,"definition"),r.add(o.value)}function gn(e){e.required!==void 0&&typeof e.required!="boolean"&&v(e,"definition"),[e.label,e.hint,e.unit].some(t=>t!==void 0&&typeof t!="string")&&v(e,"definition"),e.type==="boolean"&&[e.trueLabel,e.falseLabel].some(t=>t!==void 0&&typeof t!="string")&&v(e,"definition")}function Ue(e,t){(!t||typeof t!="object"||Array.isArray(t)||!["text","number","boolean","enum","date"].includes(t.type))&&v(t??{type:"text"},"definition"),gn(t),(t.type==="number"||t.type==="boolean")&&e.valueType!==t.type&&v(t,"type"),(t.type==="text"||t.type==="date")&&e.valueType!=="text"&&v(t,"type"),t.type==="number"&&mn(t),t.type==="text"&&t.maxLength!==void 0&&(!Number.isInteger(t.maxLength)||t.maxLength<0)&&v(t,"definition"),t.type==="date"&&fn(t),t.type==="enum"&&hn(e,t)}function pn(e,t,n){if(!e.editable)throw new T("readonly");n&&Ue(e,n);const r=ae(e,t);return n?(n.required&&typeof r=="string"&&!r.trim()&&v(n,"required"),r===null||r===""?(n.required&&v(n,"required"),r):(n.type==="number"&&dn(n,r),n.type==="date"&&un(n,r),n.type==="text"&&n.maxLength!==void 0&&[...String(r)].length>n.maxLength&&v(n,"length",n.maxLength),n.type==="enum"&&!n.options.some(o=>Object.is(o.value,r))&&v(n,"choice"),r)):r}class b extends Error{constructor(t){super(`Report calculation: ${t}`),this.code=t,this.name="ReportCalculationError"}}function K(e){if(!e?.aborted)return;const t=new Error("Calculation cancelled");throw t.name="AbortError",t}async function te(e,t=1){const n=Math.floor(e.scanned/2048);if(e.scanned+=t,e.scanned>e.maxScanned)throw new b("limit");K(e.signal),Math.floor(e.scanned/2048)>n&&(await e.yieldToHost(),K(e.signal))}function pe(e){return e.table?.role==="header"?-Math.max(1,e.grid?.cells.length??1):e.table?.rowIndex??0}function Ee(e,t,n){if(![t.pageIndex,t.componentIndex,t.rowIndex,t.columnIndex].every(i=>Number.isSafeInteger(i)&&i>=0))throw new b("selection");const r=e.pages[t.pageIndex]?.components[t.componentIndex];if(!r?.grid||t.rowIndex>=r.grid.cells.length)throw new b("selection");const o=r.grid.colWidthsMm?.length??r.grid.cells.reduce((i,a)=>Math.max(i,a.length),1);if(t.columnIndex>=o)throw new b("selection");const s=r.table,l=e.pages[n.pageIndex]?.components[n.componentIndex]?.table;if(s&&l&&s.id===l.id){const i=l.columnKeys.indexOf(s.columnKeys[t.columnIndex]??"");if(i<0)throw new b("selection");return{grid:s.id,row:pe(r)+t.rowIndex,column:i}}return{grid:`${t.pageIndex}:${t.componentIndex}`,row:t.rowIndex,column:t.columnIndex}}function wn(e,t,n){const r=Ee(e,t.anchor,t.anchor),o=Ee(e,t.focus,t.anchor);if(r.grid!==o.grid)throw new b("selection");const s=(Math.abs(r.row-o.row)+1)*(Math.abs(r.column-o.column)+1);if(!Number.isSafeInteger(s)||s>n)throw new b("limit");return{grid:r.grid,rowStart:Math.min(r.row,o.row),rowEnd:Math.max(r.row,o.row),columnStart:Math.min(r.column,o.column),columnEnd:Math.max(r.column,o.column),origin:e.pages[t.anchor.pageIndex].components[t.anchor.componentIndex].table}}function vn(e){if(!e)return!1;const t=e.replace(/"[^"]*"|\\.|\[(?![hms]+\])[^\]]*\]/gi,"");return/[ymdhs]/i.test(t)}function bn(e){if(e.valueType==="text"||e.valueType==="boolean"||vn(e.numberFormat))return null;const t=e.value;if(typeof t!="number"||!Number.isFinite(t))return null;if(Number.isInteger(t)&&!Number.isSafeInteger(t))throw new b("precision");return t}function yn(e,t,n){if(e.seen.has(n))return;e.seen.add(n),e.selected++;const r=t?bn(t):null;r===null?e.excluded++:e.values.push(r)}function xn(e,t,n,r){return r.origin?e.table?.id===r.origin.id:`${t}:${n}`===r.grid}function Mn(e,t,n){return n.origin?n.origin.columnKeys.indexOf(e.table.columnKeys[t]??""):t}function Tn(e,t,n,r){const o=r.origin?pe(e)+t:t,s=Mn(e,n,r);return o<r.rowStart||o>r.rowEnd||s<r.columnStart||s>r.columnEnd?null:`${r.grid}:${o}:${s}`}function En(e,t){const n=t.origin?pe(e):0,r=Math.max(0,t.rowStart-n),o=Math.min(e.grid.cells.length,t.rowEnd-n+1);return o>r?o:0}async function Sn(e,t,n,r,o){const s=e.grid;if(t>r.maxScanned)throw new b("limit");const l=s.colWidthsMm?.length??s.cells.reduce((a,c)=>Math.max(a,c.length),1);if(l>r.maxScanned)throw new b("limit");const i=new Map;for(let a=0;a<t;a++){a>0&&a%2048===0&&(await r.yieldToHost(),K(r.signal));let c=0;for(const d of s.cells[a]){for(await te(r);c<l&&(i.get(c)??0)>a;)c++;if(c>=l)break;const u=Math.max(1,Math.min(d?.colSpan??1,l-c)),m=Math.min(s.cells.length,a+Math.max(1,d?.rowSpan??1));u>1&&await te(r,u-1);for(let g=c;g<c+u;g++)i.set(g,m);const h=Tn(e,a,c,n);h&&yn(o,d,h),c+=u}}}async function Cn(e,t,n){const r={values:[],seen:new Set,excluded:0,selected:0};for(let o=0;o<e.pages.length;o++){await te(n);const s=e.pages[o];for(let l=0;l<s.components.length;l++){await te(n);const i=s.components[l];if(!i.grid||!xn(i,o,l,t)||i.table&&i.table.role!=="body")continue;const a=En(i,t);a&&await Sn(i,a,t,n,r)}}return r}function G(e){if(!Number.isFinite(e))throw new b("overflow");return e}function Rn(e){let t=0,n=0;for(const r of e){const o=r-n,s=G(t+o);n=s-t-o,t=s}return t}async function Se(e,t){let n=[...e],r=new Array(e.length);for(let s=1;s<e.length;s*=2){for(let l=0;l<e.length;l+=s*2){const i=Math.min(l+s,e.length),a=Math.min(l+s*2,e.length);let c=l,d=i;for(let u=l;u<a;u++)r[u]=d>=a||c<i&&n[c]<=n[d]?n[c++]:n[d++],u%2048===0&&(await t.yieldToHost(),K(t.signal))}[n,r]=[r,n]}const o=Math.floor(n.length/2);return n.length%2?n[o]:G(n[o-1]/2+n[o]/2)}function Pn(e){const t=Rn(e);let n=1/0,r=-1/0;for(const o of e)n=Math.min(n,o),r=Math.max(r,o);return{SUM:t,AVERAGE:t/e.length,AVG:t/e.length,MIN:n,MAX:r,COUNT:e.length}}function Ke(e,t){if(typeof e!="string"||e.length>256)throw new b("expression");const n=e.toUpperCase().match(/(?:\d+(?:\.\d*)?|\.\d+)(?:E[+-]?\d+)?|[A-Z_]+|[()+\-*/]|\S/g)??[];if(!n.length||n.length>64)throw new b("expression");let r=0;function o(i){if(i>16)throw new b("expression");const a=n[r++];if(a==="+"||a==="-")return(a==="-"?-1:1)*o(i+1);if(a==="("){const c=s(0,i+1);if(n[r++]!==")")throw new b("expression");return c}if(a&&/^(?:SUM|AVERAGE|AVG|MIN|MAX|COUNT|MEDIAN)$/.test(a)&&Object.prototype.hasOwnProperty.call(t,a))return G(t[a]);if(a&&/^(?:\d+(?:\.\d*)?|\.\d+)(?:E[+-]?\d+)?$/.test(a))return G(Number(a));throw new b("expression")}function s(i,a){let c=o(a);for(;r<n.length;){const d=n[r],u=d==="+"||d==="-"?1:d==="*"||d==="/"?2:0;if(!u||u<i)break;r++;const m=s(u+1,a+1);if(d==="/"&&m===0)throw new b("division");c=G(d==="+"?c+m:d==="-"?c-m:d==="*"?c*m:c/m)}return c}const l=s(1,0);if(r!==n.length)throw new b("expression");return l}function In(e){const t=e.maxCells??1e5,n=e.maxScannedCells??2e5,r=e.precision??2;if(![t,n].every(o=>Number.isSafeInteger(o)&&o>=1&&o<=2e6))throw new b("limit");if(!Number.isInteger(r)||r<0||r>12)throw new b("precision");return{maxCells:t,maxScanned:n,precision:r}}async function An(e,t,n={}){const r=In(n),o={scanned:0,maxScanned:r.maxScanned,signal:n.signal,yieldToHost:n.yieldToHost??(()=>new Promise(a=>setTimeout(a,0)))};K(o.signal);const s=await Cn(e,wn(e,t,r.maxCells),o),l=n.operation??"sum";if(!["sum","average","min","max","count","median","expression"].includes(l))throw new b("expression");let i=null;if(l==="count")i=s.values.length;else if(s.values.length)if(l==="median")i=await Se(s.values,o);else{const a=Pn(s.values);l==="expression"?(/\bMEDIAN\b/i.test(n.expression??"")&&(a.MEDIAN=await Se(s.values,o)),i=Ke(n.expression??"",a)):i=a[l.toUpperCase()]}if(K(o.signal),i!==null&&Number.isInteger(i)&&!Number.isSafeInteger(i))throw new b("precision");return{value:i,formatted:i===null?"—":i.toFixed(r.precision),numericCells:s.values.length,excludedCells:s.excluded,selectedCells:s.selected,precision:r.precision}}exports.DEFAULT_BORDER_PT=x.DEFAULT_BORDER_PT;exports.DEFAULT_FONT_FAMILY=x.DEFAULT_FONT_FAMILY;exports.DEFAULT_FONT_PT=x.DEFAULT_FONT_PT;exports.DEFAULT_STROKE_COLOR=x.DEFAULT_STROKE_COLOR;exports.DEFAULT_TEXT_COLOR=x.DEFAULT_TEXT_COLOR;exports.LINE_HEIGHT=x.LINE_HEIGHT;exports.RENDER_PLAN_SCHEMA_VERSION=x.RENDER_PLAN_SCHEMA_VERSION;exports.SCHEMA_VERSION_MACH=x.SCHEMA_VERSION_MACH;exports.isImageBackedComponent=x.isImageBackedComponent;exports.isRichText=x.isRichText;exports.PaginatePageLimitError=F.PaginatePageLimitError;exports.ReportSourceError=F.ReportSourceError;exports.createReportSource=F.createReportSource;exports.datasetJsonSchema=F.datasetJsonSchema;exports.defineReport=F.defineReport;exports.evalStyleRule=F.evalStyleRule;exports.formatValue=F.formatValue;exports.paginateTemplate=F.paginateTemplate;exports.parseDateLocal=F.parseDateLocal;exports.toExcelNumberFormat=F.toExcelNumberFormat;exports.toNumber=F.toNumber;exports.validateDatasetRows=F.validateDatasetRows;exports.CSS_DPI=f.CSS_DPI;exports.MM_PER_INCH=f.MM_PER_INCH;exports.PAPER_SIZES=f.PAPER_SIZES;exports.mergeComponentStyles=f.mergeComponentStyles;exports.mmToPx=f.mmToPx;exports.mmToPxFactor=f.mmToPxFactor;exports.ptToPx=f.ptToPx;exports.pxToMm=f.pxToMm;exports.resolveBoxBorders=f.resolveBoxBorders;exports.resolveFontSize=f.resolveFontSize;exports.resolveLineHeight=f.resolveLineHeight;exports.resolveStroke=f.resolveStroke;exports.resolveTextColor=f.resolveTextColor;exports.round=f.round;exports.assertRenderPlan=ne.assertRenderPlan;exports.validateComponent=ne.validateComponent;exports.validatePage=ne.validatePage;exports.validateRenderPlan=ne.validateRenderPlan;exports.charWidthEm=_.charWidthEm;exports.createCanvasMeasurer=_.createCanvasMeasurer;exports.createHeuristicMeasurer=_.createHeuristicMeasurer;exports.heuristicMeasurer=_.heuristicMeasurer;exports.measureTextMm=_.measureTextMm;exports.wrapText=_.wrapText;exports.resolveGridLayout=j.resolveGridLayout;exports.OutputAssetError=W.OutputAssetError;exports.resolvePlanAssets=W.resolvePlanAssets;exports.OutputFidelityError=$.OutputFidelityError;exports.inspectOutputCapabilities=$.inspectOutputCapabilities;exports.reportOutputDiagnostics=$.reportOutputDiagnostics;exports.REPORT_TEMPLATE_DOCUMENT_VERSION=D.REPORT_TEMPLATE_DOCUMENT_VERSION;exports.ReportTemplateError=D.ReportTemplateError;exports.createTemplateRegistry=D.createTemplateRegistry;exports.defineReportTemplate=D.defineReportTemplate;exports.parseReportTemplate=D.parseReportTemplate;exports.serializeReportTemplate=D.serializeReportTemplate;exports.validateReportTemplate=D.validateReportTemplate;exports.validateReportTemplateDocument=D.validateReportTemplateDocument;exports.ReportParamValidationError=V.ReportParamValidationError;exports.assertReportParams=V.assertReportParams;exports.isReportDate=V.isReportDate;exports.reportParamsJsonSchema=V.reportParamsJsonSchema;exports.validateReportParamDefinitions=V.validateReportParamDefinitions;exports.validateReportParams=V.validateReportParams;exports.PageBuilder=$e;exports.ReportCalculationError=b;exports.ReportCellEditError=T;exports.ReportCellFieldError=je;exports.ReportTemplateStoreError=H;exports.TemplateBuilder=Oe;exports.applyReportCellEdit=Zt;exports.applyReportCellEditBatch=nn;exports.applyReportEditResult=ln;exports.calculateReportSelection=An;exports.classOf=P;exports.columnsFromContract=Ct;exports.computePageWindow=Ie;exports.createCanvasPager=Et;exports.createMemoryTemplateStore=Dt;exports.createProviderReport=Ot;exports.createReportCellEdit=qt;exports.createReportCellEditBatch=tn;exports.createReportCellResolver=ie;exports.createTableTemplate=Lt;exports.createTemplate=St;exports.createTemplateManager=$t;exports.evaluateReportAggregateExpression=Ke;exports.formatReportCellEdit=Y;exports.formatReportClipboard=on;exports.getReportCellContext=oe;exports.measurePageSizePx=re;exports.parseReportCellFieldInput=pn;exports.parseReportCellInput=ae;exports.parseReportClipboard=sn;exports.planFontSizePx=ft;exports.renderComponent=ue;exports.renderPage=Pe;exports.renderPlan=lt;exports.renderPlanToCanvas=xt;exports.renderPlanToCanvasAsync=Tt;exports.renderPlanToImages=bt;exports.reportCellEditKey=se;exports.resolvePaper=he;exports.summarizeReportCellEdits=rn;exports.validateReportCellFieldDefinition=Ue;
package/dist/index.d.cts CHANGED
@@ -45,6 +45,9 @@ export declare interface BoxBorders {
45
45
  inner: boolean;
46
46
  }
47
47
 
48
+ /** Read-only local analysis. Never changes the plan, formulas, datasets or business persistence. */
49
+ export declare function calculateReportSelection(plan: RenderPlan, selection: ReportCalculationSelection, options?: ReportSelectionCalculationOptions): Promise<ReportSelectionCalculationResult>;
50
+
48
51
  export declare type CanvasImageLoader = (source: string, signal?: AbortSignal) => Promise<CanvasImageSource>;
49
52
 
50
53
  export declare interface CanvasPager {
@@ -279,6 +282,9 @@ export declare function defineReportTemplate(document: Omit<ReportTemplateDocume
279
282
  */
280
283
  export declare function evalStyleRule(row: Record<string, unknown>, when: StyleRule["when"]): boolean;
281
284
 
285
+ /** A tiny arithmetic parser: no functions, property access, globals, assignments or executable source. */
286
+ export declare function evaluateReportAggregateExpression(expression: string, values: Readonly<Record<string, number>>): number;
287
+
282
288
  /** 同步 text/raw value,所有输出后端读取同一份更新后的 RenderPlan。 */
283
289
  export declare function formatReportCellEdit(context: ReportCellContext, value: ReportCellValue): string;
284
290
 
@@ -717,6 +723,20 @@ export declare function renderPlanToImages(plan: RenderPlan, options?: ImageRend
717
723
  /** 模板存储文档版本;与渲染计划版本独立演进。 */
718
724
  export declare const REPORT_TEMPLATE_DOCUMENT_VERSION = "1.0";
719
725
 
726
+ export declare class ReportCalculationError extends Error {
727
+ readonly code: ReportCalculationErrorCode;
728
+ constructor(code: ReportCalculationErrorCode);
729
+ }
730
+
731
+ export declare type ReportCalculationErrorCode = "selection" | "limit" | "expression" | "division" | "overflow" | "precision";
732
+
733
+ export declare type ReportCalculationOperation = "sum" | "average" | "min" | "max" | "count" | "median" | "expression";
734
+
735
+ export declare interface ReportCalculationSelection {
736
+ anchor: ReportCellAddress;
737
+ focus: ReportCellAddress;
738
+ }
739
+
720
740
  /** 预览中的物理坐标;合并单元格使用左上角坐标。 */
721
741
  export declare interface ReportCellAddress {
722
742
  pageIndex: number;
@@ -1014,6 +1034,28 @@ export declare interface ReportSaveResult {
1014
1034
  diagnostics?: ReportDiagnostic[];
1015
1035
  }
1016
1036
 
1037
+ export declare interface ReportSelectionCalculationOptions {
1038
+ operation?: ReportCalculationOperation;
1039
+ /** Only aggregate names, finite numeric constants, + - * / and parentheses. No cell/Excel formulas. */
1040
+ expression?: string;
1041
+ precision?: number;
1042
+ maxCells?: number;
1043
+ maxScannedCells?: number;
1044
+ signal?: AbortSignal;
1045
+ /** Cooperative scheduler; default yields to the browser/Node event loop. */
1046
+ yieldToHost?: () => Promise<void>;
1047
+ }
1048
+
1049
+ export declare interface ReportSelectionCalculationResult {
1050
+ value: number | null;
1051
+ formatted: string;
1052
+ numericCells: number;
1053
+ excludedCells: number;
1054
+ selectedCells: number;
1055
+ /** IEEE-754 arithmetic; presentation rounding does not change source values. */
1056
+ precision: number;
1057
+ }
1058
+
1017
1059
  export declare interface ReportSource extends ReportFetcher {
1018
1060
  getParamDefs(reportIds: string[]): ReportParamDef[];
1019
1061
  }
package/dist/index.d.ts CHANGED
@@ -45,6 +45,9 @@ export declare interface BoxBorders {
45
45
  inner: boolean;
46
46
  }
47
47
 
48
+ /** Read-only local analysis. Never changes the plan, formulas, datasets or business persistence. */
49
+ export declare function calculateReportSelection(plan: RenderPlan, selection: ReportCalculationSelection, options?: ReportSelectionCalculationOptions): Promise<ReportSelectionCalculationResult>;
50
+
48
51
  export declare type CanvasImageLoader = (source: string, signal?: AbortSignal) => Promise<CanvasImageSource>;
49
52
 
50
53
  export declare interface CanvasPager {
@@ -279,6 +282,9 @@ export declare function defineReportTemplate(document: Omit<ReportTemplateDocume
279
282
  */
280
283
  export declare function evalStyleRule(row: Record<string, unknown>, when: StyleRule["when"]): boolean;
281
284
 
285
+ /** A tiny arithmetic parser: no functions, property access, globals, assignments or executable source. */
286
+ export declare function evaluateReportAggregateExpression(expression: string, values: Readonly<Record<string, number>>): number;
287
+
282
288
  /** 同步 text/raw value,所有输出后端读取同一份更新后的 RenderPlan。 */
283
289
  export declare function formatReportCellEdit(context: ReportCellContext, value: ReportCellValue): string;
284
290
 
@@ -717,6 +723,20 @@ export declare function renderPlanToImages(plan: RenderPlan, options?: ImageRend
717
723
  /** 模板存储文档版本;与渲染计划版本独立演进。 */
718
724
  export declare const REPORT_TEMPLATE_DOCUMENT_VERSION = "1.0";
719
725
 
726
+ export declare class ReportCalculationError extends Error {
727
+ readonly code: ReportCalculationErrorCode;
728
+ constructor(code: ReportCalculationErrorCode);
729
+ }
730
+
731
+ export declare type ReportCalculationErrorCode = "selection" | "limit" | "expression" | "division" | "overflow" | "precision";
732
+
733
+ export declare type ReportCalculationOperation = "sum" | "average" | "min" | "max" | "count" | "median" | "expression";
734
+
735
+ export declare interface ReportCalculationSelection {
736
+ anchor: ReportCellAddress;
737
+ focus: ReportCellAddress;
738
+ }
739
+
720
740
  /** 预览中的物理坐标;合并单元格使用左上角坐标。 */
721
741
  export declare interface ReportCellAddress {
722
742
  pageIndex: number;
@@ -1014,6 +1034,28 @@ export declare interface ReportSaveResult {
1014
1034
  diagnostics?: ReportDiagnostic[];
1015
1035
  }
1016
1036
 
1037
+ export declare interface ReportSelectionCalculationOptions {
1038
+ operation?: ReportCalculationOperation;
1039
+ /** Only aggregate names, finite numeric constants, + - * / and parentheses. No cell/Excel formulas. */
1040
+ expression?: string;
1041
+ precision?: number;
1042
+ maxCells?: number;
1043
+ maxScannedCells?: number;
1044
+ signal?: AbortSignal;
1045
+ /** Cooperative scheduler; default yields to the browser/Node event loop. */
1046
+ yieldToHost?: () => Promise<void>;
1047
+ }
1048
+
1049
+ export declare interface ReportSelectionCalculationResult {
1050
+ value: number | null;
1051
+ formatted: string;
1052
+ numericCells: number;
1053
+ excludedCells: number;
1054
+ selectedCells: number;
1055
+ /** IEEE-754 arithmetic; presentation rounding does not change source values. */
1056
+ precision: number;
1057
+ }
1058
+
1017
1059
  export declare interface ReportSource extends ReportFetcher {
1018
1060
  getParamDefs(reportIds: string[]): ReportParamDef[];
1019
1061
  }