@agile-team/mach-report 2.10.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +6 -2
  2. package/dist/ExcelBindingWizard-CjIiVox-.cjs +1 -0
  3. package/dist/ExcelBindingWizard-Dxm-K5HL.js +1240 -0
  4. package/dist/ParamEditor-D-Hf5xfO.cjs +1 -0
  5. package/dist/ParamEditor-DRGxzxeO.js +381 -0
  6. package/dist/ReportBatchPanel-BYgg0EDB.cjs +1 -0
  7. package/dist/ReportBatchPanel-Bby5yLzU.js +287 -0
  8. package/dist/ReportPreview-DWXROHBP.cjs +6 -0
  9. package/dist/ReportPreview-DiNXhQI0.js +4138 -0
  10. package/dist/ReportTemplateLibrary-C6CO7YCT.cjs +1 -0
  11. package/dist/ReportTemplateLibrary-DfzDXRvr.js +260 -0
  12. package/dist/RuleEditor-C2QsOHOs.cjs +1 -0
  13. package/dist/RuleEditor-D9wQHrkf.js +2024 -0
  14. package/dist/TemplateReviewPanel-BKofGrV9.js +222 -0
  15. package/dist/TemplateReviewPanel-DwtOcLue.cjs +1 -0
  16. package/dist/analytics.cjs +1 -1
  17. package/dist/analytics.d.cts +2 -0
  18. package/dist/analytics.d.ts +2 -0
  19. package/dist/analytics.js +29 -29
  20. package/dist/batch-Bt3Fd27Z.cjs +1 -0
  21. package/dist/batch-mRqhhhjt.js +364 -0
  22. package/dist/computed-Bvk0W15F.js +521 -0
  23. package/dist/computed-CGV2a809.cjs +1 -0
  24. package/dist/config-B612mw0x.js +525 -0
  25. package/dist/config-BRoLo2oj.cjs +1 -0
  26. package/dist/designer.cjs +2 -2
  27. package/dist/designer.d.cts +659 -9
  28. package/dist/designer.d.ts +659 -9
  29. package/dist/designer.js +2030 -1824
  30. package/dist/index.cjs +8 -8
  31. package/dist/index.d.cts +147 -3
  32. package/dist/index.d.ts +147 -3
  33. package/dist/index.js +639 -592
  34. package/dist/injection-keys-Db_DyLkm.cjs +1 -0
  35. package/dist/injection-keys-e85udZCp.js +7 -0
  36. package/dist/list-cell-BuYn4tGF.cjs +1 -0
  37. package/dist/{list-cell-Dxyi7DOw.js → list-cell-ClFra1zS.js} +54 -40
  38. package/dist/matrix-DVyWiYsd.cjs +1 -0
  39. package/dist/matrix-yZsGnldA.js +227 -0
  40. package/dist/param-validation-BlHHXs6u.js +153 -0
  41. package/dist/param-validation-DCK039V1.cjs +1 -0
  42. package/dist/pdf.cjs +25 -25
  43. package/dist/pdf.d.cts +3 -0
  44. package/dist/pdf.d.ts +3 -0
  45. package/dist/pdf.js +677 -677
  46. package/dist/plugin-BDTU4D94.cjs +1 -0
  47. package/dist/plugin-Cd5G2QQn.js +22 -0
  48. package/dist/region-binding-workflow-CXDmt9Bs.js +977 -0
  49. package/dist/region-binding-workflow-DhQvu1co.cjs +3 -0
  50. package/dist/{report-params-B_VCihAh.js → report-params-B44imUd4.js} +1 -1
  51. package/dist/{report-params-CjWrjPl6.cjs → report-params-SJfhKgaX.cjs} +1 -1
  52. package/dist/server/node.d.cts +5 -2
  53. package/dist/server/node.d.ts +5 -2
  54. package/dist/server-node.cjs +1 -1
  55. package/dist/server-node.js +87 -87
  56. package/dist/server.cjs +1 -1
  57. package/dist/server.d.cts +201 -2
  58. package/dist/server.d.ts +201 -2
  59. package/dist/server.js +557 -658
  60. package/dist/style.css +1 -1
  61. package/dist/template-registry-WNXdkiET.js +506 -0
  62. package/dist/template-registry-ukBGlm8N.cjs +1 -0
  63. package/dist/template-review-BXp2oyqg.cjs +1 -0
  64. package/dist/template-review-BdcXSYbx.js +1616 -0
  65. package/dist/tree-BX380Rr7.cjs +1 -0
  66. package/dist/tree-CqcQ99NM.js +172 -0
  67. package/dist/{validate-UUy9yP4K.js → validate-7s0yn6ii.js} +44 -44
  68. package/dist/validate-DsRiNw8h.cjs +1 -0
  69. package/dist/vue/async.d.cts +93 -4
  70. package/dist/vue/async.d.ts +93 -4
  71. package/dist/vue/index.d.cts +145 -7
  72. package/dist/vue/index.d.ts +145 -7
  73. package/dist/vue-async.cjs +1 -1
  74. package/dist/vue-async.js +5 -5
  75. package/dist/vue.cjs +1 -1
  76. package/dist/vue.js +116 -113
  77. package/dist/{workbook-session-B-bW5_yR.js → workbook-session-BKOTwcoq.js} +1 -1
  78. package/dist/{workbook-session-D7RtdNo0.cjs → workbook-session-CLYLhZWu.cjs} +1 -1
  79. package/dist/worker.cjs +1 -1
  80. package/dist/worker.d.cts +5 -2
  81. package/dist/worker.d.ts +5 -2
  82. package/dist/worker.js +1 -1
  83. package/dist/xlsx.cjs +3 -3
  84. package/dist/xlsx.d.cts +129 -2
  85. package/dist/xlsx.d.ts +129 -2
  86. package/dist/xlsx.js +336 -242
  87. package/package.json +1 -1
  88. package/dist/ExcelBindingWizard-CF7RplWm.cjs +0 -1
  89. package/dist/ExcelBindingWizard-qhwEderR.js +0 -842
  90. package/dist/ReportPreview-BE1tCHqE.js +0 -4604
  91. package/dist/ReportPreview-QKRKQOe3.cjs +0 -6
  92. package/dist/RuleEditor-BA36yIV6.js +0 -1723
  93. package/dist/RuleEditor-CczJ6mJm.cjs +0 -1
  94. package/dist/TemplateReviewPanel-CHi4Alqa.cjs +0 -1
  95. package/dist/TemplateReviewPanel-Dz0G5o83.js +0 -217
  96. package/dist/binding-preview-BWsdf_z2.cjs +0 -2
  97. package/dist/binding-preview-DILq0-0f.js +0 -649
  98. package/dist/decimal-CI1OAczk.js +0 -87
  99. package/dist/decimal-CQA0xJex.cjs +0 -1
  100. package/dist/list-cell-CyM1ZlRN.cjs +0 -1
  101. package/dist/matrix-BbXarwyk.js +0 -661
  102. package/dist/matrix-Cm65WLLP.cjs +0 -1
  103. package/dist/param-validation-BWNjLcN0.js +0 -116
  104. package/dist/param-validation-CiTxFeZ8.cjs +0 -1
  105. package/dist/plugin-CThk42vJ.cjs +0 -1
  106. package/dist/plugin-tGn7-5oF.js +0 -25
  107. package/dist/template-registry-CGWTLtIA.cjs +0 -1
  108. package/dist/template-registry-DzlQs3OF.js +0 -434
  109. package/dist/template-review-D1RoNCPw.cjs +0 -1
  110. package/dist/template-review-fnteXRng.js +0 -1473
  111. package/dist/validate-Bf6ccFr2.cjs +0 -1
package/dist/worker.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("./task-events-DQ276fn2.cjs"),A=require("./validate-Bf6ccFr2.cjs"),u="mach-report-worker/1";class l extends Error{constructor(r){super(r.message),this.name=r.name,this.code=r.code,this.path=r.path,this.issues=r.issues,this.diagnostics=r.diagnostics}}function p(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function L(e){return p(e)?["rows","pages","cells"].every(r=>typeof e[r]=="number"&&Number.isSafeInteger(e[r])&&e[r]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function P(e){return Array.isArray(e)&&e.every(r=>p(r)&&typeof r.code=="string"&&typeof r.message=="string"&&["info","warning","error"].includes(r.severity))}function T(e){return p(e)&&Object.values(e).every(r=>p(r)&&(r.revision===void 0||typeof r.revision=="string")&&(r.sourceToken===void 0||typeof r.sourceToken=="string"))}function v(e,r){if(!p(e)||!L(e.stats)||!P(e.diagnostics)||!T(e.revisions))return!1;if(r==="prepare")return A.validateRenderPlan(e.plan).ok;const t=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===t}function W(e){if(!e||typeof e!="object")return{message:String(e)};const r={};for(const t of["code","path","field","message"]){const o=e[t];typeof o=="string"&&(r[t]=o)}return r}function j(e){const r=W(e);if(!p(e))return r;for(const t of["format","severity","kind","nid"])typeof e[t]=="string"&&(r[t]=e[t]);for(const t of["pageIndex","componentIndex"])Number.isSafeInteger(e[t])&&e[t]>=0&&(r[t]=e[t]);return Array.isArray(e.componentPath)&&e.componentPath.every(t=>Number.isSafeInteger(t)&&t>=0)&&(r.componentPath=e.componentPath),r}function O(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const r=e;return{name:e.name,message:e.message,...typeof r.code=="string"?{code:r.code}:{},...typeof r.path=="string"?{path:r.path}:{},...Array.isArray(r.issues)?{issues:r.issues.map(W)}:{},...Array.isArray(r.diagnostics)?{diagnostics:r.diagnostics.map(j)}:{}}}function S(e){if(!e||typeof e!="object")return!1;const r=e;return r.protocol===u&&typeof r.id=="string"&&(r.operation==="prepare"||r.operation==="export")&&!!r.input&&typeof r.input=="object"}async function N(e,r,t){try{const o=r.operation==="prepare"?await e.prepare({...r.input,onEvent:t}):await e.export({...r.input,onEvent:t});return{protocol:u,id:r.id,result:o}}catch(o){return{protocol:u,id:r.id,error:O(o)}}}function z(e){const r=e.result;return!r||!("bytes"in r)||!(r.bytes.buffer instanceof ArrayBuffer)?[]:[r.bytes.buffer]}function _(e,r){if(!p(e)||typeof e.taskId!="string"||!e.taskId||r.taskId!==void 0&&e.taskId!==r.taskId||e.correlationId!==r.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!r.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const t of["completed","total"])if(e[t]!==void 0&&(typeof e[t]!="number"||!Number.isFinite(e[t])||e[t]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let q=0;function w(e){const r=new Error("报表 Worker 任务已取消");return r.name="AbortError",Object.defineProperty(r,"cause",{value:e}),r}function B(e,r){if(!e||typeof e!="object")return;const t=e;return t.protocol===u&&t.id===r?t:void 0}function F(e,r={}){const t=r.timeoutMs??12e4;if(!Number.isFinite(t)||t<=0||t>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(i,c,n,d)=>n?.aborted?Promise.reject(w(n.reason)):new Promise((I,b)=>{let g;try{g=e()}catch(a){b(a);return}const R=`mach-report-${Date.now()}-${++q}`;let y=!1,E=()=>{},k;const f=(a,s)=>{y||(y=!0,k&&clearTimeout(k),E(),n?.removeEventListener("abort",h),Promise.resolve().then(()=>g.terminate()).then(()=>a===void 0?I(s):b(a),m=>b(a??m)))},h=()=>f(w(n?.reason)),M=a=>{const s=B(a,R);if(!(!s||y)){if("type"in s&&s.type==="event"){const m="event"in s?s.event:void 0;_(m,c)?x.notifyReportTaskEvent(d,m,n):f(new Error("报表 Worker 返回无效阶段事件"));return}s.error&&typeof s.error.name=="string"&&typeof s.error.message=="string"?f(new l(s.error)):v(s.result,i)&&(i!=="export"||"format"in s.result&&"format"in c&&s.result.format===c.format)?f(void 0,s.result):f(new Error("报表 Worker 返回无效响应"))}};try{if(E=g.subscribe(M,a=>f(a??new Error("报表 Worker 执行失败"))),y){E();return}if(n?.addEventListener("abort",h,{once:!0}),k=setTimeout(()=>f(new l({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${t}ms`})),t),n?.aborted)h();else{const{onEvent:a,signal:s,...m}=c;g.postMessage({protocol:u,id:R,operation:i,input:m})}}catch(a){f(a)}});return{prepare:(i,c,n)=>o("prepare",i,c,n),export:(i,c,n)=>o("export",i,c,n)}}function $(e,r={}){return F(()=>{const t=e();return{postMessage:o=>t.postMessage(o),terminate:()=>t.terminate(),subscribe:(o,i)=>{const c=d=>o(d.data),n=d=>i(d instanceof ErrorEvent?new Error(d.message):new Error("报表 Worker 消息无法解码"));return t.addEventListener("message",c),t.addEventListener("error",n),t.addEventListener("messageerror",n),()=>{t.removeEventListener("message",c),t.removeEventListener("error",n),t.removeEventListener("messageerror",n)}}}},r)}function D(e,r=globalThis){const t=o=>{S(o.data)&&N(e,o.data,i=>r.postMessage({protocol:u,id:o.data.id,type:"event",event:i})).then(i=>r.postMessage(i,z(i)))};return r.addEventListener("message",t),()=>r.removeEventListener("message",t)}exports.ReportWorkerError=l;exports.createBrowserReportExecutor=$;exports.serveReportWorker=D;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("./task-events-DQ276fn2.cjs"),A=require("./validate-DsRiNw8h.cjs"),u="mach-report-worker/1";class l extends Error{constructor(r){super(r.message),this.name=r.name,this.code=r.code,this.path=r.path,this.issues=r.issues,this.diagnostics=r.diagnostics}}function p(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function L(e){return p(e)?["rows","pages","cells"].every(r=>typeof e[r]=="number"&&Number.isSafeInteger(e[r])&&e[r]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function P(e){return Array.isArray(e)&&e.every(r=>p(r)&&typeof r.code=="string"&&typeof r.message=="string"&&["info","warning","error"].includes(r.severity))}function T(e){return p(e)&&Object.values(e).every(r=>p(r)&&(r.revision===void 0||typeof r.revision=="string")&&(r.sourceToken===void 0||typeof r.sourceToken=="string"))}function v(e,r){if(!p(e)||!L(e.stats)||!P(e.diagnostics)||!T(e.revisions))return!1;if(r==="prepare")return A.validateRenderPlan(e.plan).ok;const t=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===t}function W(e){if(!e||typeof e!="object")return{message:String(e)};const r={};for(const t of["code","path","field","message"]){const o=e[t];typeof o=="string"&&(r[t]=o)}return r}function j(e){const r=W(e);if(!p(e))return r;for(const t of["format","severity","kind","nid"])typeof e[t]=="string"&&(r[t]=e[t]);for(const t of["pageIndex","componentIndex"])Number.isSafeInteger(e[t])&&e[t]>=0&&(r[t]=e[t]);return Array.isArray(e.componentPath)&&e.componentPath.every(t=>Number.isSafeInteger(t)&&t>=0)&&(r.componentPath=e.componentPath),r}function O(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const r=e;return{name:e.name,message:e.message,...typeof r.code=="string"?{code:r.code}:{},...typeof r.path=="string"?{path:r.path}:{},...Array.isArray(r.issues)?{issues:r.issues.map(W)}:{},...Array.isArray(r.diagnostics)?{diagnostics:r.diagnostics.map(j)}:{}}}function S(e){if(!e||typeof e!="object")return!1;const r=e;return r.protocol===u&&typeof r.id=="string"&&(r.operation==="prepare"||r.operation==="export")&&!!r.input&&typeof r.input=="object"}async function N(e,r,t){try{const o=r.operation==="prepare"?await e.prepare({...r.input,onEvent:t}):await e.export({...r.input,onEvent:t});return{protocol:u,id:r.id,result:o}}catch(o){return{protocol:u,id:r.id,error:O(o)}}}function z(e){const r=e.result;return!r||!("bytes"in r)||!(r.bytes.buffer instanceof ArrayBuffer)?[]:[r.bytes.buffer]}function _(e,r){if(!p(e)||typeof e.taskId!="string"||!e.taskId||r.taskId!==void 0&&e.taskId!==r.taskId||e.correlationId!==r.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!r.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const t of["completed","total"])if(e[t]!==void 0&&(typeof e[t]!="number"||!Number.isFinite(e[t])||e[t]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let q=0;function w(e){const r=new Error("报表 Worker 任务已取消");return r.name="AbortError",Object.defineProperty(r,"cause",{value:e}),r}function B(e,r){if(!e||typeof e!="object")return;const t=e;return t.protocol===u&&t.id===r?t:void 0}function F(e,r={}){const t=r.timeoutMs??12e4;if(!Number.isFinite(t)||t<=0||t>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(i,c,n,d)=>n?.aborted?Promise.reject(w(n.reason)):new Promise((I,b)=>{let g;try{g=e()}catch(a){b(a);return}const R=`mach-report-${Date.now()}-${++q}`;let y=!1,E=()=>{},k;const f=(a,s)=>{y||(y=!0,k&&clearTimeout(k),E(),n?.removeEventListener("abort",h),Promise.resolve().then(()=>g.terminate()).then(()=>a===void 0?I(s):b(a),m=>b(a??m)))},h=()=>f(w(n?.reason)),M=a=>{const s=B(a,R);if(!(!s||y)){if("type"in s&&s.type==="event"){const m="event"in s?s.event:void 0;_(m,c)?x.notifyReportTaskEvent(d,m,n):f(new Error("报表 Worker 返回无效阶段事件"));return}s.error&&typeof s.error.name=="string"&&typeof s.error.message=="string"?f(new l(s.error)):v(s.result,i)&&(i!=="export"||"format"in s.result&&"format"in c&&s.result.format===c.format)?f(void 0,s.result):f(new Error("报表 Worker 返回无效响应"))}};try{if(E=g.subscribe(M,a=>f(a??new Error("报表 Worker 执行失败"))),y){E();return}if(n?.addEventListener("abort",h,{once:!0}),k=setTimeout(()=>f(new l({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${t}ms`})),t),n?.aborted)h();else{const{onEvent:a,signal:s,...m}=c;g.postMessage({protocol:u,id:R,operation:i,input:m})}}catch(a){f(a)}});return{prepare:(i,c,n)=>o("prepare",i,c,n),export:(i,c,n)=>o("export",i,c,n)}}function $(e,r={}){return F(()=>{const t=e();return{postMessage:o=>t.postMessage(o),terminate:()=>t.terminate(),subscribe:(o,i)=>{const c=d=>o(d.data),n=d=>i(d instanceof ErrorEvent?new Error(d.message):new Error("报表 Worker 消息无法解码"));return t.addEventListener("message",c),t.addEventListener("error",n),t.addEventListener("messageerror",n),()=>{t.removeEventListener("message",c),t.removeEventListener("error",n),t.removeEventListener("messageerror",n)}}}},r)}function D(e,r=globalThis){const t=o=>{S(o.data)&&N(e,o.data,i=>r.postMessage({protocol:u,id:o.data.id,type:"event",event:i})).then(i=>r.postMessage(i,z(i)))};return r.addEventListener("message",t),()=>r.removeEventListener("message",t)}exports.ReportWorkerError=l;exports.createBrowserReportExecutor=$;exports.serveReportWorker=D;
package/dist/worker.d.cts CHANGED
@@ -43,6 +43,8 @@ declare interface GridCell {
43
43
  value?: string | number | boolean | null;
44
44
  /** Excel 数字格式(例如 #,##0.00 / 0.00%),不改变 text。 */
45
45
  numberFormat?: string;
46
+ /** Physical left inset for hierarchical labels; raw value stays unchanged. */
47
+ indentMm?: number;
46
48
  /** 编辑输入类型;省略时只按原始值推断,数字字符串不会被转换为数值。 */
47
49
  valueType?: "text" | "number" | "boolean";
48
50
  /** 单元格级编辑控制;预览仍需显式开启 editing。 */
@@ -94,6 +96,7 @@ declare interface PlanGrid {
94
96
  }
95
97
 
96
98
  declare interface PlanPage {
99
+ meta?: Record<string, unknown>;
97
100
  /** wide 表示完整自然列宽;页面仅为预览的垂直窗口分段。 */
98
101
  layout?: "page" | "wide";
99
102
  pageWidthMm: number;
@@ -174,7 +177,7 @@ declare interface ReportParamDef {
174
177
  field: string;
175
178
  /** 显示名(缺省用 field) */
176
179
  label?: string;
177
- type?: "text" | "number" | "date" | "select";
180
+ type?: "text" | "number" | "date" | "month" | "year" | "dateRange" | "select";
178
181
  /** select 选项 */
179
182
  options?: Array<{
180
183
  label: string;
@@ -183,7 +186,7 @@ declare interface ReportParamDef {
183
186
  defaultValue?: string;
184
187
  required?: boolean;
185
188
  placeholder?: string;
186
- /** 数字上下界;date 参数使用 YYYY-MM-DD 字符串(含边界)。 */
189
+ /** 数字上下界;日期/月/年使用对应规范字符串;dateRange 对两端使用 YYYY-MM-DD 边界(含边界)。 */
187
190
  min?: number | string;
188
191
  max?: number | string;
189
192
  minLength?: number;
package/dist/worker.d.ts CHANGED
@@ -43,6 +43,8 @@ declare interface GridCell {
43
43
  value?: string | number | boolean | null;
44
44
  /** Excel 数字格式(例如 #,##0.00 / 0.00%),不改变 text。 */
45
45
  numberFormat?: string;
46
+ /** Physical left inset for hierarchical labels; raw value stays unchanged. */
47
+ indentMm?: number;
46
48
  /** 编辑输入类型;省略时只按原始值推断,数字字符串不会被转换为数值。 */
47
49
  valueType?: "text" | "number" | "boolean";
48
50
  /** 单元格级编辑控制;预览仍需显式开启 editing。 */
@@ -94,6 +96,7 @@ declare interface PlanGrid {
94
96
  }
95
97
 
96
98
  declare interface PlanPage {
99
+ meta?: Record<string, unknown>;
97
100
  /** wide 表示完整自然列宽;页面仅为预览的垂直窗口分段。 */
98
101
  layout?: "page" | "wide";
99
102
  pageWidthMm: number;
@@ -174,7 +177,7 @@ declare interface ReportParamDef {
174
177
  field: string;
175
178
  /** 显示名(缺省用 field) */
176
179
  label?: string;
177
- type?: "text" | "number" | "date" | "select";
180
+ type?: "text" | "number" | "date" | "month" | "year" | "dateRange" | "select";
178
181
  /** select 选项 */
179
182
  options?: Array<{
180
183
  label: string;
@@ -183,7 +186,7 @@ declare interface ReportParamDef {
183
186
  defaultValue?: string;
184
187
  required?: boolean;
185
188
  placeholder?: string;
186
- /** 数字上下界;date 参数使用 YYYY-MM-DD 字符串(含边界)。 */
189
+ /** 数字上下界;日期/月/年使用对应规范字符串;dateRange 对两端使用 YYYY-MM-DD 边界(含边界)。 */
187
190
  min?: number | string;
188
191
  max?: number | string;
189
192
  minLength?: number;
package/dist/worker.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as A } from "./task-events-Dpsvf_t2.js";
2
- import { c as M } from "./validate-UUy9yP4K.js";
2
+ import { c as M } from "./validate-7s0yn6ii.js";
3
3
  const u = "mach-report-worker/1";
4
4
  class R extends Error {
5
5
  constructor(r) {
package/dist/xlsx.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("./progress-BnLiS5eH.cjs"),f=require("./workbook-session-D7RtdNo0.cjs"),C=require("./render-plan-7xpGrCEl.cjs"),A=require("./grid-geometry-CZ_cYB6O.cjs"),y=require("./style-UgIJSA1F.cjs"),I=require("./capabilities-CsZ-pNHR.cjs"),u=require("./binding-preview-BWsdf_z2.cjs");function M(t,e){const i=t??e;if(!Number.isSafeInteger(i)||i<=0)throw new Error("Excel 图片字节预算应为正安全整数");return i}function z(t,e){const i=t.imageData;if(!i||!/^data:image\/(png|jpe?g);base64,/i.test(i))return;if(i.length>Math.ceil(e/3)*4+64)throw new Error("Excel 单张图片超过字节预算");const n=i.indexOf(","),r=i.slice(n+1);if(!/^[A-Za-z0-9+/]+={0,2}$/.test(r)||r.length%4!==0)throw new Error("Excel 图片不是有效的 base64 数据");const o=r.length/4*3-(r.endsWith("==")?2:r.endsWith("=")?1:0);if(o>e)throw new Error("Excel 单张图片超过字节预算");const a=/^data:image\/png;/i.test(i)?"png":"jpeg",s=atob(r.slice(0,12));if(a==="png"?!s.startsWith(`‰PNG\r
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./progress-BnLiS5eH.cjs"),w=require("./workbook-session-CLYLhZWu.cjs"),W=require("./render-plan-7xpGrCEl.cjs"),R=require("./grid-geometry-CZ_cYB6O.cjs"),C=require("./style-UgIJSA1F.cjs"),P=require("./capabilities-CsZ-pNHR.cjs"),m=require("./region-binding-workflow-DhQvu1co.cjs");function v(e,t){const i=e??t;if(!Number.isSafeInteger(i)||i<=0)throw new Error("Excel 图片字节预算应为正安全整数");return i}function z(e,t){const i=e.imageData;if(!i||!/^data:image\/(png|jpe?g);base64,/i.test(i))return;if(i.length>Math.ceil(t/3)*4+64)throw new Error("Excel 单张图片超过字节预算");const n=i.indexOf(","),r=i.slice(n+1);if(!/^[A-Za-z0-9+/]+={0,2}$/.test(r)||r.length%4!==0)throw new Error("Excel 图片不是有效的 base64 数据");const o=r.length/4*3-(r.endsWith("==")?2:r.endsWith("=")?1:0);if(o>t)throw new Error("Excel 单张图片超过字节预算");const l=/^data:image\/png;/i.test(i)?"png":"jpeg",s=atob(r.slice(0,12));if(l==="png"?!s.startsWith(`‰PNG\r
2
2
  
3
- `):!s.startsWith("ÿØÿ"))throw new Error("Excel 图片内容与 PNG/JPEG 类型不一致");return{base64:`data:image/${a};base64,${r}`,key:`${a}:${r}`,extension:a,bytes:o}}function P(t,e,i){let n=i*72/25.4;if(!Number.isFinite(n)||e+Math.ceil(n/409)-1>1048576)throw new Error("Excel 图片占位超过工作表行数上限");for(;n>0;){if(e>1048576)throw new Error("Excel 图片占位超过工作表行数上限");const r=Math.min(409,n);t.getRow(e++).height=r,n-=r}return e}function B(t,e,i){let n=Math.round(e*36e3),r=0;if(!Number.isSafeInteger(n))throw new Error("Excel 图片锚点超出安全坐标范围");for(t.properties.defaultColWidth??=8.43;r<16384;){const o=t.getColumn(r+1).width??t.properties.defaultColWidth,a=Math.round(f.excelColumnWidthToMm(o)*36e3);if(!Number.isSafeInteger(a)||a<=0)throw new Error("Excel 图片锚点所在列宽无效");if(n<a)return{col:r+n/a,row:i-1,nativeCol:r,nativeColOff:n,nativeRow:i-1,nativeRowOff:0};n-=a,r++}throw new Error("Excel 图片锚点超过16384列上限")}function R(t,e,i){const n=M(e.maxImageBytes,16777216),r=M(e.maxTotalImageBytes,32*1024*1024),o=M(e.maxImages,1e3),a=new Map,s=new Map;let l=0;return{write(h,c,d){if(![c.widthMm,c.heightMm,c.leftMm].every(Number.isFinite)||c.widthMm<0||c.heightMm<0||c.leftMm<0)throw new Error("Excel 图片尺寸无效");if(!c.widthMm||!c.heightMm)return d;const g=s.get(c.imageData)??z(c,n);if(g&&s.set(c.imageData,g),!g)return i.push(`${c.nid??c.kind}: Excel 图片仅支持 PNG/JPEG data URI,已跳过`),d;let m=a.get(g.key);if(m===void 0){if(a.size>=o)throw new Error("Excel 唯一图片数量超过预算");if(l+g.bytes>r)throw new Error("Excel 图片总字节数超过预算");m=t.addImage({base64:g.base64,extension:g.extension}),a.set(g.key,m),l+=g.bytes}const p=P(h,d,c.heightMm);return h.addImage(m,{tl:B(h,c.leftMm,d),ext:{width:c.widthMm*96/25.4,height:c.heightMm*96/25.4},editAs:"oneCell"}),p}}}const k=72/25.4,F=32767,O=253;function E(t,e){if(typeof t!="string")return;if(t.length>F)throw new Error(`Excel 单元格 ${e} 最多支持 32767 个字符,无法无损导出;内容未裁剪`);let i=0;for(let n=0;n<t.length;n++)if(t.charCodeAt(n)===10&&++i>O)throw new Error(`Excel 单元格 ${e} 最多支持 253 个换行,无法无损导出;内容未改写`)}function x(t){if(!t)return;const e=t.replace("#","");return/^[0-9a-fA-F]{6}$/.test(e)?`FF${e.toUpperCase()}`:void 0}function $(t,e={}){t.font={name:e.fontFamily,bold:e.bold===!0,italic:e.italic===!0,underline:e.underline===!0,size:y.resolveFontSize(e).fontSizePt,color:x(e.color)?{argb:x(e.color)}:void 0}}const b={a3:{width:297,height:420,code:8},a4:{width:210,height:297,code:9},a5:{width:148,height:210,code:11}};function L(t,e,i,n){if(e&&e!=="auto")return b[e].code;const r=Math.min(t.pageWidthMm,t.pageHeightMm),o=Math.max(t.pageWidthMm,t.pageHeightMm),a=Object.values(b).find(s=>Math.abs(r-s.width)<=1&&Math.abs(o-s.height)<=1);return a?a.code:(n.push(`page ${i+1}: 自定义纸张 ${t.pageWidthMm}×${t.pageHeightMm}mm 无对应 Excel 纸型,打印设置回退 A4;可显式配置 paperSize`),b.a4.code)}function N(t,e,i,n){const r=typeof e.text=="string"?e.text:"";if(i!=="raw"||!Object.prototype.hasOwnProperty.call(e,"value")){E(r,t.address),t.value=r;return}const o=e.value;if(o===null||typeof o=="string"||typeof o=="boolean"||typeof o=="number"&&Number.isFinite(o)){E(o,t.address),t.value=o,e.numberFormat&&(t.numFmt=e.numberFormat);return}E(r,t.address),t.value=r,n.push(`原始单元格值无效,已保留显示文本:${t.address}`)}function G(t){const i=t.components.filter(n=>n.table!==void 0)[0]?.table;if(!(!i||typeof i.id!="string"||!i.id.trim()||!Array.isArray(i.columnKeys)||!i.columnKeys.length)){for(const n of t.components){if(n.table){if(!n.grid||n.table.id!==i.id)return;continue}if(n.grid||n.kind!=="text"&&!C.isImageBackedComponent(n)||n.richParagraphs?.length&&!n.text&&!n.lines?.length)return}return{id:i.id,title:i.title,wide:i.layout==="wide"||t.layout==="wide"}}}function D(t,e){const i=new Set;for(const[n,r]of t.pages.entries())if(!e[n])for(const o of r.components)typeof o.table?.id=="string"&&i.add(o.table.id);return i}function v(t){return t.layout==="wide"||t.components.some(e=>e.table?.layout==="wide")}function _(t,e,i){const n=[],r=t.pages.map(G),o=D(t,r);for(const[a,s]of t.pages.entries()){const l=r[a],h=l&&!o.has(l.id),c=e==="pages"||!h?void 0:l;if(e==="continuous"&&!c)throw new Error(`page ${a+1}: continuous Excel 需要完整、单一的逻辑表来源;自由布局请使用 sheetMode: 'pages'`);const d=c!==void 0&&(e==="continuous"||c.wide);!d&&e!=="pages"&&v(s)&&i.push(`page ${a+1}: 混合或缺少逻辑表来源,已保留独立 Sheet,未猜测合并内容`);const g=n[n.length-1];d&&g?.continuous&&g.tableId===c.id?g.pages.push({page:s,index:a}):n.push({pages:[{page:s,index:a}],continuous:d,...d?{tableId:c.id,title:c.title}:{}})}return n}function S(t,e,i){return!t||t.length===e.length&&t.every((n,r)=>i(n,e[r]))}function j(t,e,i,n){const r=t.table,o=e.columns.map(l=>l.size),a=S(n.keys,r.columnKeys,(l,h)=>l===h),s=S(n.widths,o,(l,h)=>Math.abs(l-h)<=.001);if(r.columnKeys.length!==o.length||!a||!s)throw new Error(`page ${i+1}: 连续 Excel 逻辑表 ${r.id} 的列结构或列宽不一致`);if(n.keys??=r.columnKeys,n.widths??=o,r.role==="header"){if(r.rowIndex!==-1)throw new Error(`page ${i+1}: 连续 Excel 表头 rowIndex 必须为 -1`);n.headerSeen=!0}else{if(!["body","group-header","subtotal","grand-total"].includes(r.role)||r.rowIndex!==n.expectedRow)throw new Error(`page ${i+1}: 连续 Excel 逻辑行来源不连续或重复(期望 ${n.expectedRow})`);n.expectedRow+=e.rows.length}if(e.cells.some(l=>l.cell.children?.length))throw new Error(`page ${i+1}: 连续 Excel 暂不支持嵌套组件;请使用独立 Sheet 导出并检查告警`)}function q(t,e){const i={expectedRow:0,headerSeen:!1};for(const{page:n,index:r}of t.pages)for(const o of n.components){const a=e.get(o);o.table&&a&&j(o,a,r,i)}if(!i.headerSeen)throw new Error("连续 Excel 逻辑表缺少明确表头来源")}function H(t,e,i){let n=(t?.replace(/[\\/*?:[\]]/g," ").replace(/\s+/g," ").trim()||`Sheet${e+1}`).slice(0,31).replace(/^'+|'+$/g,"").trim()||`Sheet${e+1}`;n.toLowerCase()==="history"&&(n+=" 报表");let r=n,o=1;for(;i.has(r.toLowerCase());){const a=` (${++o})`;r=n.slice(0,31-a.length)+a}return i.add(r.toLowerCase()),r}function X(t){const e=new Set;function i(n,r,o,a){return n<=r?n:(e.has(o)||(t.push(a),e.add(o)),r)}return{column:n=>i(n,255,"column","Excel 单列宽度上限为 255 字符,超宽列已收敛至 255;单元格值完整保留,显示范围可能受限"),row:n=>i(n,409,"row","Excel 行高上限为 409pt,超高行已收敛至 409pt;单元格值完整保留,显示范围可能受限")}}function K(t){const e=t.pages.flatMap(({page:o,index:a},s)=>o.components.filter(l=>!t.continuous||(l.pageAnchor!=="header"||s===0)&&(l.pageAnchor!=="footer"||s===t.pages.length-1)).map(l=>({comp:l,pageIndex:a}))),i=new Map;let n=1,r=0;for(const{comp:o}of e)if(o.grid){const a=A.resolveGridLayout(o.grid,o.widthMm,o.heightMm);i.set(o,a),n=Math.max(n,a.columns.length)}else o.kind==="text"&&(r=Math.max(r,o.widthMm));if(n>16384)throw new Error("Excel 最多支持 16384 列,无法无损导出此报表");return{components:e,grids:i,columnCount:n,textWidthMm:r}}function J(t,e,i){const{page:n,index:r}=t.pages[0],o=e!==void 0&&e!=="auto";return(t.continuous||v(n))&&!o?{}:{pageSetup:{paperSize:L(n,e,r,i),orientation:n.pageWidthMm>n.pageHeightMm?"landscape":"portrait",fitToPage:!0,...t.continuous?{fitToWidth:1,fitToHeight:0}:{}}}}function U(t){const e=x(t.borderColor??t.lineColor),i={style:"thin",...e?{color:{argb:e}}:{}};return{...t.borderTop!==!1?{top:i}:{},...t.borderLeft!==!1?{left:i}:{},...t.borderBottom!==!1?{bottom:i}:{},...t.borderRight!==!1?{right:i}:{}}}function V(t,e){t.alignment={horizontal:e.align??"left",vertical:e.verticalAlign??"middle",wrapText:!0};const i=x(e.backgroundColor);i&&(t.fill={type:"pattern",pattern:"solid",fgColor:{argb:i}}),t.border=U(e),$(t,e)}function Z(t,e){for(const[i,n]of e.columns.entries()){const r=t.sheet.getColumn(i+1),o=t.limits.column(f.mmToExcelColumnWidth(n.size));(r.width==null||r.width<o)&&(r.width=o)}}function Q(t,e,i){for(const[n,r]of e.rows.entries()){const o=t.sheet.getRow(i+n),a=t.limits.row(r.size*k);(o.height==null||o.height<a)&&(o.height=a)}}function Y(t,e,i,n){const r=Math.max(1,Math.min(e.cell.colSpan??1,i.columns.length-e.ci)),o=Math.max(1,Math.min(e.cell.rowSpan??1,i.rows.length-e.ri));(r>1||o>1)&&t.mergeCells(n+e.ri,e.ci+1,n+e.ri+o-1,e.ci+r)}function ee(t,e,i,n,r){if(n+i.rows.length-1>1048576)throw new Error("Excel 最多支持 1048576 行,无法无损导出此报表");Q(t,i,n);for(const o of i.cells){const a=t.sheet.getCell(n+o.ri,o.ci+1);N(a,o.cell,t.valueMode,t.warnings),o.cell.children?.length&&t.warnings.push(`page ${r+1} ${e.nid??e.kind} cell ${o.ri+1}:${o.ci+1}: 嵌套组件内容暂不支持 xlsx 导出,已跳过`),V(a,y.mergeComponentStyles(e.style,o.cell.style)),Y(t.sheet,o,i,n)}return n+i.rows.length}function te(t,e,i,n,r){const o=Array.isArray(e.lines)&&e.lines.length>0?e.lines.join(`
4
- `):e.text??"";if(e.richParagraphs?.length){const h=o.length===0?"富文本内容暂不支持 xlsx 导出,已跳过":"富文本按已有文本回退导出,内联样式未保留";t.warnings.push(`page ${r+1} ${e.nid??e.kind}: ${h}`)}const a=t.sheet.getRow(i),s=a.getCell(1);E(o,s.address),s.value=o,s.alignment={horizontal:e.style?.align??"left",vertical:e.style?.verticalAlign??"middle",wrapText:!0};const l=x(e.style?.backgroundColor);return l&&(s.fill={type:"pattern",pattern:"solid",fgColor:{argb:l}}),$(s,e.style),n>1&&t.sheet.mergeCells(i,1,i,n),a.height=t.limits.row(e.heightMm*k),i+1}function ne(t,e,i){const n=e+i-1;t.views=[{state:"frozen",ySplit:n,xSplit:0}],t.pageSetup.printTitlesRow=`1:${n}`}function ie(t,e,i,n){!e.grids.size&&e.textWidthMm>0&&(t.sheet.getColumn(1).width=t.limits.column(f.mmToExcelColumnWidth(e.textWidthMm)));for(const a of e.grids.values())Z(t,a);let r=1,o=!1;for(const{comp:a,pageIndex:s}of e.components){const l=i&&a.table?.role==="header";if(l&&o)continue;if(r>1048576)throw new Error("Excel 最多支持 1048576 行,无法无损导出此报表");const h=e.grids.get(a);h?(l&&(ne(t.sheet,r,h.rows.length),o=!0),r=ee(t,a,h,r,s)):a.kind==="text"?r=te(t,a,r,e.columnCount,s):C.isImageBackedComponent(a)?r=n.write(t.sheet,a,r):t.warnings.push(`page ${s+1} ${a.nid??a.kind}: 组件类型 ${a.kind} 暂不支持 xlsx 导出,已跳过`)}}function re(t){if(t.valueMode!==void 0&&t.valueMode!=="text"&&t.valueMode!=="raw")throw new Error("xlsx valueMode 必须是 text 或 raw");if(t.paperSize!==void 0&&t.paperSize!=="auto"&&!Object.prototype.hasOwnProperty.call(b,t.paperSize))throw new Error("xlsx paperSize 必须是 auto、a3、a4 或 a5");if(t.sheetMode!==void 0&&!["auto","pages","continuous"].includes(t.sheetMode))throw new Error("xlsx sheetMode 必须是 auto、pages 或 continuous")}async function oe(t,e={}){re(e),w.assertOutputActive(e.signal);const i=I.reportOutputDiagnostics(t,"xlsx",e),n=new f.ExcelJSRuntime.Workbook,r=[],o=R(n,e,r),a=X(r),s=_(t,e.sheetMode,r),l=new Set;for(const[c,d]of s.entries()){const g=K(d);d.continuous&&q(d,g.grids);const m=d.pages[0].page,p=e.sheetName?.(c)??H(d.title,c,l);l.add(p.toLowerCase());const W=n.addWorksheet(p,J(d,e.paperSize,r)),T=e.valueMode??(v(m)||d.continuous?"raw":"text");w.assertOutputActive(e.signal),ie({sheet:W,warnings:r,limits:a,valueMode:T},g,d.continuous,o),await w.outputCheckpoint(e,c+1,s.length)}w.assertOutputActive(e.signal);const h=await n.xlsx.writeBuffer();return w.assertOutputActive(e.signal),{workbook:n,buffer:h,warnings:r,diagnostics:i}}exports.importExcelTemplate=f.importExcelTemplate;exports.inspectExcelWorkbook=f.inspectExcelWorkbook;exports.openExcelWorkbook=f.openExcelWorkbook;exports.bindExcelTemplate=u.bindExcelTemplate;exports.createExcelBindingDocument=u.createExcelBindingDocument;exports.createExcelBindingSession=u.createExcelBindingSession;exports.excelBindingRowRange=u.excelBindingRowRange;exports.getExcelSheetWindow=u.getExcelSheetWindow;exports.parseExcelBindingSession=u.parseExcelBindingSession;exports.validateExcelBindingFields=u.validateExcelBindingFields;exports.validateExcelBindingRecipe=u.validateExcelBindingRecipe;exports.validateExcelBindingRegions=u.validateExcelBindingRegions;exports.renderPlanToXlsx=oe;
3
+ `):!s.startsWith("ÿØÿ"))throw new Error("Excel 图片内容与 PNG/JPEG 类型不一致");return{base64:`data:image/${l};base64,${r}`,key:`${l}:${r}`,extension:l,bytes:o}}function O(e,t,i){let n=i*72/25.4;if(!Number.isFinite(n)||t+Math.ceil(n/409)-1>1048576)throw new Error("Excel 图片占位超过工作表行数上限");for(;n>0;){if(t>1048576)throw new Error("Excel 图片占位超过工作表行数上限");const r=Math.min(409,n);e.getRow(t++).height=r,n-=r}return t}function G(e,t,i){let n=Math.round(t*36e3),r=0;if(!Number.isSafeInteger(n))throw new Error("Excel 图片锚点超出安全坐标范围");for(e.properties.defaultColWidth??=8.43;r<16384;){const o=e.getColumn(r+1).width??e.properties.defaultColWidth,l=Math.round(w.excelColumnWidthToMm(o)*36e3);if(!Number.isSafeInteger(l)||l<=0)throw new Error("Excel 图片锚点所在列宽无效");if(n<l)return{col:r+n/l,row:i-1,nativeCol:r,nativeColOff:n,nativeRow:i-1,nativeRowOff:0};n-=l,r++}throw new Error("Excel 图片锚点超过16384列上限")}function N(e,t,i){const n=v(t.maxImageBytes,16777216),r=v(t.maxTotalImageBytes,32*1024*1024),o=v(t.maxImages,1e3),l=new Map,s=new Map;let a=0;return{write(d,c,h){if(![c.widthMm,c.heightMm,c.leftMm].every(Number.isFinite)||c.widthMm<0||c.heightMm<0||c.leftMm<0)throw new Error("Excel 图片尺寸无效");if(!c.widthMm||!c.heightMm)return h;const g=s.get(c.imageData)??z(c,n);if(g&&s.set(c.imageData,g),!g)return i.push(`${c.nid??c.kind}: Excel 图片仅支持 PNG/JPEG data URI,已跳过`),h;let f=l.get(g.key);if(f===void 0){if(l.size>=o)throw new Error("Excel 唯一图片数量超过预算");if(a+g.bytes>r)throw new Error("Excel 图片总字节数超过预算");f=e.addImage({base64:g.base64,extension:g.extension}),l.set(g.key,f),a+=g.bytes}const u=O(d,h,c.heightMm);return d.addImage(f,{tl:G(d,c.leftMm,h),ext:{width:c.widthMm*96/25.4,height:c.heightMm*96/25.4},editAs:"oneCell"}),u}}}function B(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function A(e,t){const i=e.meta?.xlsxFlow;if(i===void 0)return;if(!B(i)||i.version!=="1.0"||!Number.isSafeInteger(i.columnStart)||Number(i.columnStart)<0)throw new Error("Excel 多区域几何标记无效,不能按列序猜测输出");if(!e.grid)throw new Error("Excel 多区域输出只接受显式网格组件");const n=i,r=e.grid.colWidthsMm;if(!r?.length||n.columnStart+r.length>t.length||r.some((o,l)=>Math.abs(o-t[n.columnStart+l])>.001))throw new Error("Excel 多区域列位置与网格列宽不一致");return n}function I(e){const t=e.meta?.xlsxFlow;if(t===void 0){if(e.components.some(n=>n.meta?.xlsxFlow!==void 0))throw new Error("Excel 多区域页面缺少完整列几何标记");return}const i=L(t,e.meta?.reportScope);for(const n of e.components){const r=A(n,i.widths);if(!r)throw new Error("Excel 多区域页面混入没有区域几何的组件,请使用独立页面模板");const o=i.widths.slice(0,r.columnStart).reduce((s,a)=>s+a,e.marginLeftMm??0),l=n.grid.colWidthsMm.reduce((s,a)=>s+a,0);if(Math.abs(o-n.leftMm)>.01||Math.abs(l-n.widthMm)>.01)throw new Error("Excel 多区域标记与真实横向位置不一致")}return i}function L(e,t){if(!B(e)||e.version!=="1.0"||typeof e.sheet!="string"||!e.sheet.trim()||typeof e.templateId!="string"||!e.templateId.trim())throw new Error("Excel 多区域工作表标识无效");if(!Array.isArray(e.fullWidthsMm)||!e.fullWidthsMm.length||e.fullWidthsMm.length>16384||e.fullWidthsMm.some(i=>typeof i!="number"||!Number.isFinite(i)||i<=0||i>2e3))throw new Error("Excel 多区域完整列宽无效");if(t!==void 0&&(typeof t!="string"||!t.trim()))throw new Error("Excel 多区域报表命名空间无效");return{key:JSON.stringify([t??e.templateId,e.sheet]),sheet:e.sheet,widths:e.fullWidthsMm}}function S(e){return Math.round(e*1e6)/1e6}function D(e,t,i,n,r){return e.components.filter(o=>n?o.pageAnchor==="header"?t===0:o.pageAnchor==="footer"?t===i-1:o.table?.role!=="header"?!0:r.has(o.table.id)?!1:(r.add(o.table.id),!0):!0)}function j(e,t,i,n){const r=e.components.filter(l=>!t.includes(l)&&l.table?.role==="header"),o=t.filter(l=>!l.pageAnchor).reduce((l,s)=>Math.max(l,s.topMm+s.heightMm),e.marginTopMm??0);return t.map(l=>{let s=l.topMm;return i&&l.pageAnchor==="footer"&&(s=o),s-=r.filter(a=>a.topMm+a.heightMm<=s+.001).reduce((a,d)=>a+d.heightMm,0),{component:l,layout:R.resolveGridLayout(l.grid,l.widthMm,l.heightMm),top:s,column:A(l,n).columnStart}})}function _(e,t,i){const n=t.length-1;if(n*i.length>1e6)throw new Error("Excel 多区域单页超过 100 万几何单元格,请减小预览分页高度或列数");const r=new Map(t.map((s,a)=>[s,a])),o=new Map,l=new Map;for(const s of e)for(const a of s.layout.cells){if(!Object.keys(a.cell).length)continue;const d=r.get(S(s.top+a.yMm)),c=r.get(S(s.top+a.yMm+a.heightMm)),h=s.column+a.ci,g=h+(a.cell.colSpan??1),f=`${d}:${h}`;for(let u=d;u<c;u++)for(let x=h;x<g;x++){const M=`${u}:${x}`;if(l.has(M))throw new Error("Excel 多区域实际单元格互相覆盖,已终止输出,未覆盖已有内容");l.set(M,f)}o.set(f,{...a.cell,style:C.mergeComponentStyles(s.component.style,a.cell.style),rowSpan:c-d,colSpan:g-h})}return Array.from({length:n},(s,a)=>{const d=[];for(let c=0;c<i.length;c++){const h=`${a}:${c}`,g=o.get(h);g?(d.push(g),c+=(g.colSpan??1)-1):l.has(h)||d.push(null)}return d})}function H(e,t){const i=new Set,n=[];let r;for(const[o,{page:l}]of e.entries()){const s=I(l);if(r&&(s.key!==r.key||s.widths.length!==r.widths.length||s.widths.some((f,u)=>Math.abs(f-r.widths[u])>.001)))throw new Error("Excel 多区域分页的工作表或列结构不一致");r??=s;const a=D(l,o,e.length,t,i),d=j(l,a,t,s.widths);if(!d.length)continue;const c=[...new Set(d.flatMap(f=>[...f.layout.rows.map(u=>S(f.top+u.pos)),S(f.top+f.component.heightMm)]))].sort((f,u)=>f-u),h=_(d,c,s.widths),g=c.slice(1).map((f,u)=>f-c[u]);n.push({kind:"rect",leftMm:0,topMm:0,widthMm:s.widths.reduce((f,u)=>f+u,0),heightMm:g.reduce((f,u)=>f+u,0),grid:{cells:h,colWidthsMm:s.widths,rowHeightsMm:g}})}return n}const T=72/25.4,q=32767,X=253;function b(e,t){if(typeof e!="string")return;if(e.length>q)throw new Error(`Excel 单元格 ${t} 最多支持 32767 个字符,无法无损导出;内容未裁剪`);let i=0;for(let n=0;n<e.length;n++)if(e.charCodeAt(n)===10&&++i>X)throw new Error(`Excel 单元格 ${t} 最多支持 253 个换行,无法无损导出;内容未改写`)}function E(e){if(!e)return;const t=e.replace("#","");return/^[0-9a-fA-F]{6}$/.test(t)?`FF${t.toUpperCase()}`:void 0}function F(e,t={}){e.font={name:t.fontFamily,bold:t.bold===!0,italic:t.italic===!0,underline:t.underline===!0,size:C.resolveFontSize(t).fontSizePt,color:E(t.color)?{argb:E(t.color)}:void 0}}const y={a3:{width:297,height:420,code:8},a4:{width:210,height:297,code:9},a5:{width:148,height:210,code:11}};function K(e,t,i,n){if(t&&t!=="auto")return y[t].code;const r=Math.min(e.pageWidthMm,e.pageHeightMm),o=Math.max(e.pageWidthMm,e.pageHeightMm),l=Object.values(y).find(s=>Math.abs(r-s.width)<=1&&Math.abs(o-s.height)<=1);return l?l.code:(n.push(`page ${i+1}: 自定义纸张 ${e.pageWidthMm}×${e.pageHeightMm}mm 无对应 Excel 纸型,打印设置回退 A4;可显式配置 paperSize`),y.a4.code)}function J(e,t,i,n){const r=typeof t.text=="string"?t.text:"";if(i!=="raw"||!Object.prototype.hasOwnProperty.call(t,"value")){b(r,e.address),e.value=r;return}const o=t.value;if(o===null||typeof o=="string"||typeof o=="boolean"||typeof o=="number"&&Number.isFinite(o)){b(o,e.address),e.value=o,t.numberFormat&&(e.numFmt=t.numberFormat);return}b(r,e.address),e.value=r,n.push(`原始单元格值无效,已保留显示文本:${e.address}`)}function U(e){const t=I(e);return t?{id:`xlsx-flow:${t.key}`,title:t.sheet,wide:!0,flow:!0}:V(e)}function V(e){const i=e.components.filter(n=>n.table!==void 0)[0]?.table;if(!(!i||typeof i.id!="string"||!i.id.trim()||!Array.isArray(i.columnKeys)||!i.columnKeys.length)){for(const n of e.components){if(n.table){if(!n.grid||n.table.id!==i.id)return;continue}if(n.grid||n.kind!=="text"&&!W.isImageBackedComponent(n)||n.richParagraphs?.length&&!n.text&&!n.lines?.length)return}return{id:i.id,title:i.title,wide:i.layout==="wide"||e.layout==="wide"}}}function Z(e,t){const i=new Set;for(const[n,r]of e.pages.entries())if(!t[n])for(const o of r.components)typeof o.table?.id=="string"&&i.add(o.table.id);return i}function k(e){return e.layout==="wide"||e.components.some(t=>t.table?.layout==="wide")}function Q(e,t,i){const n=[],r=e.pages.map(U),o=Z(e,r);for(const[l,s]of e.pages.entries()){const a=r[l],d=a&&!o.has(a.id),c=t==="pages"||!d?void 0:a;if(t==="continuous"&&!c)throw new Error(`page ${l+1}: continuous Excel 需要完整、单一的逻辑表来源;自由布局请使用 sheetMode: 'pages'`);const h=c!==void 0&&(t==="continuous"||c.wide);!h&&t!=="pages"&&k(s)&&i.push(`page ${l+1}: 混合或缺少逻辑表来源,已保留独立 Sheet,未猜测合并内容`);const g=n[n.length-1];h&&g?.continuous&&g.tableId===c.id?g.pages.push({page:s,index:l}):n.push({pages:[{page:s,index:l}],continuous:h,...h?{tableId:c.id,title:c.title}:{},...a?.flow?{flow:!0,title:a.title}:{}})}return n}function $(e,t,i){return!e||e.length===t.length&&e.every((n,r)=>i(n,t[r]))}function Y(e,t,i,n){const r=e.table,o=t.columns.map(a=>a.size),l=$(n.keys,r.columnKeys,(a,d)=>a===d),s=$(n.widths,o,(a,d)=>Math.abs(a-d)<=.001);if(r.columnKeys.length!==o.length||!l||!s)throw new Error(`page ${i+1}: 连续 Excel 逻辑表 ${r.id} 的列结构或列宽不一致`);if(n.keys??=r.columnKeys,n.widths??=o,r.role==="header"){if(r.rowIndex!==-1)throw new Error(`page ${i+1}: 连续 Excel 表头 rowIndex 必须为 -1`);n.headerSeen=!0}else{if(!["body","group-header","subtotal","grand-total"].includes(r.role)||r.rowIndex!==n.expectedRow)throw new Error(`page ${i+1}: 连续 Excel 逻辑行来源不连续或重复(期望 ${n.expectedRow})`);n.expectedRow+=t.rows.length}if(t.cells.some(a=>a.cell.children?.length))throw new Error(`page ${i+1}: 连续 Excel 暂不支持嵌套组件;请使用独立 Sheet 导出并检查告警`)}function ee(e,t){const i={expectedRow:0,headerSeen:!1};for(const{page:n,index:r}of e.pages)for(const o of n.components){const l=t.get(o);o.table&&l&&Y(o,l,r,i)}if(!i.headerSeen)throw new Error("连续 Excel 逻辑表缺少明确表头来源")}function te(e,t,i){let n=(e?.replace(/[\\/*?:[\]]/g," ").replace(/\s+/g," ").trim()||`Sheet${t+1}`).slice(0,31).replace(/^'+|'+$/g,"").trim()||`Sheet${t+1}`;n.toLowerCase()==="history"&&(n+=" 报表");let r=n,o=1;for(;i.has(r.toLowerCase());){const l=` (${++o})`;r=n.slice(0,31-l.length)+l}return i.add(r.toLowerCase()),r}function ne(e){const t=new Set;function i(n,r,o,l){return n<=r?n:(t.has(o)||(e.push(l),t.add(o)),r)}return{column:n=>i(n,255,"column","Excel 单列宽度上限为 255 字符,超宽列已收敛至 255;单元格值完整保留,显示范围可能受限"),row:n=>i(n,409,"row","Excel 行高上限为 409pt,超高行已收敛至 409pt;单元格值完整保留,显示范围可能受限")}}function ie(e){const t=e.flow?H(e.pages,e.continuous).map(o=>({comp:o,pageIndex:e.pages[0].index})):e.pages.flatMap(({page:o,index:l},s)=>o.components.filter(a=>!e.continuous||(a.pageAnchor!=="header"||s===0)&&(a.pageAnchor!=="footer"||s===e.pages.length-1)).map(a=>({comp:a,pageIndex:l}))),i=new Map;let n=1,r=0;for(const{comp:o}of t)if(o.grid){const l=R.resolveGridLayout(o.grid,o.widthMm,o.heightMm);i.set(o,l),n=Math.max(n,l.columns.length)}else o.kind==="text"&&(r=Math.max(r,o.widthMm));if(n>16384)throw new Error("Excel 最多支持 16384 列,无法无损导出此报表");return{components:t,grids:i,columnCount:n,textWidthMm:r}}function re(e,t,i){const{page:n,index:r}=e.pages[0],o=t!==void 0&&t!=="auto";return(e.continuous||k(n))&&!o?{}:{pageSetup:{paperSize:K(n,t,r,i),orientation:n.pageWidthMm>n.pageHeightMm?"landscape":"portrait",fitToPage:!0,...e.continuous?{fitToWidth:1,fitToHeight:0}:{}}}}function oe(e){const t=E(e.borderColor??e.lineColor),i={style:"thin",...t?{color:{argb:t}}:{}};return{...e.borderTop!==!1?{top:i}:{},...e.borderLeft!==!1?{left:i}:{},...e.borderBottom!==!1?{bottom:i}:{},...e.borderRight!==!1?{right:i}:{}}}function le(e,t){e.alignment={horizontal:t.align??"left",vertical:t.verticalAlign??"middle",wrapText:!0};const i=E(t.backgroundColor);i&&(e.fill={type:"pattern",pattern:"solid",fgColor:{argb:i}}),e.border=oe(t),F(e,t)}function se(e,t){for(const[i,n]of t.columns.entries()){const r=e.sheet.getColumn(i+1),o=e.limits.column(w.mmToExcelColumnWidth(n.size));(r.width==null||r.width<o)&&(r.width=o)}}function ae(e,t,i){for(const[n,r]of t.rows.entries()){const o=e.sheet.getRow(i+n),l=e.limits.row(r.size*T);(o.height==null||o.height<l)&&(o.height=l)}}function ce(e,t,i,n){const r=Math.max(1,Math.min(t.cell.colSpan??1,i.columns.length-t.ci)),o=Math.max(1,Math.min(t.cell.rowSpan??1,i.rows.length-t.ri));(r>1||o>1)&&e.mergeCells(n+t.ri,t.ci+1,n+t.ri+o-1,t.ci+r)}function de(e,t,i,n,r){if(n+i.rows.length-1>1048576)throw new Error("Excel 最多支持 1048576 行,无法无损导出此报表");ae(e,i,n);for(const o of i.cells){const l=e.sheet.getCell(n+o.ri,o.ci+1);J(l,o.cell,e.valueMode,e.warnings),o.cell.children?.length&&e.warnings.push(`page ${r+1} ${t.nid??t.kind} cell ${o.ri+1}:${o.ci+1}: 嵌套组件内容暂不支持 xlsx 导出,已跳过`),le(l,C.mergeComponentStyles(t.style,o.cell.style)),o.cell.indentMm&&(l.alignment={...l.alignment,indent:Math.min(250,Math.max(1,Math.round(o.cell.indentMm/2.5)))}),ce(e.sheet,o,i,n)}return n+i.rows.length}function he(e,t,i,n,r){const o=Array.isArray(t.lines)&&t.lines.length>0?t.lines.join(`
4
+ `):t.text??"";if(t.richParagraphs?.length){const d=o.length===0?"富文本内容暂不支持 xlsx 导出,已跳过":"富文本按已有文本回退导出,内联样式未保留";e.warnings.push(`page ${r+1} ${t.nid??t.kind}: ${d}`)}const l=e.sheet.getRow(i),s=l.getCell(1);b(o,s.address),s.value=o,s.alignment={horizontal:t.style?.align??"left",vertical:t.style?.verticalAlign??"middle",wrapText:!0};const a=E(t.style?.backgroundColor);return a&&(s.fill={type:"pattern",pattern:"solid",fgColor:{argb:a}}),F(s,t.style),n>1&&e.sheet.mergeCells(i,1,i,n),l.height=e.limits.row(t.heightMm*T),i+1}function ge(e,t,i){const n=t+i-1;e.views=[{state:"frozen",ySplit:n,xSplit:0}],e.pageSetup.printTitlesRow=`1:${n}`}function fe(e,t,i,n){!t.grids.size&&t.textWidthMm>0&&(e.sheet.getColumn(1).width=e.limits.column(w.mmToExcelColumnWidth(t.textWidthMm)));for(const l of t.grids.values())se(e,l);let r=1,o=!1;for(const{comp:l,pageIndex:s}of t.components){const a=i&&l.table?.role==="header";if(a&&o)continue;if(r>1048576)throw new Error("Excel 最多支持 1048576 行,无法无损导出此报表");const d=t.grids.get(l);d?(a&&(ge(e.sheet,r,d.rows.length),o=!0),r=de(e,l,d,r,s)):l.kind==="text"?r=he(e,l,r,t.columnCount,s):W.isImageBackedComponent(l)?r=n.write(e.sheet,l,r):e.warnings.push(`page ${s+1} ${l.nid??l.kind}: 组件类型 ${l.kind} 暂不支持 xlsx 导出,已跳过`)}}function ue(e){if(e.valueMode!==void 0&&e.valueMode!=="text"&&e.valueMode!=="raw")throw new Error("xlsx valueMode 必须是 text 或 raw");if(e.paperSize!==void 0&&e.paperSize!=="auto"&&!Object.prototype.hasOwnProperty.call(y,e.paperSize))throw new Error("xlsx paperSize 必须是 auto、a3、a4 或 a5");if(e.sheetMode!==void 0&&!["auto","pages","continuous"].includes(e.sheetMode))throw new Error("xlsx sheetMode 必须是 auto、pages 或 continuous")}async function me(e,t={}){ue(t),p.assertOutputActive(t.signal);const i=P.reportOutputDiagnostics(e,"xlsx",t),n=new w.ExcelJSRuntime.Workbook,r=[],o=N(n,t,r),l=ne(r),s=Q(e,t.sheetMode,r),a=new Set;for(const[c,h]of s.entries()){const g=ie(h);h.continuous&&!h.flow&&ee(h,g.grids);const f=h.pages[0].page,u=t.sheetName?.(c)??te(h.title,c,a);a.add(u.toLowerCase());const x=n.addWorksheet(u,re(h,t.paperSize,r)),M=t.valueMode??(k(f)||h.continuous||h.flow?"raw":"text");p.assertOutputActive(t.signal),fe({sheet:x,warnings:r,limits:l,valueMode:M},g,h.continuous,o),await p.outputCheckpoint(t,c+1,s.length)}p.assertOutputActive(t.signal);const d=await n.xlsx.writeBuffer();return p.assertOutputActive(t.signal),{workbook:n,buffer:d,warnings:r,diagnostics:i}}exports.importExcelTemplate=w.importExcelTemplate;exports.inspectExcelWorkbook=w.inspectExcelWorkbook;exports.openExcelWorkbook=w.openExcelWorkbook;exports.bindExcelTemplate=m.bindExcelTemplate;exports.createExcelBindingDocument=m.createExcelBindingDocument;exports.createExcelBindingSession=m.createExcelBindingSession;exports.createExcelRegionBindingDocument=m.createExcelRegionBindingDocument;exports.createExcelRegionBindingSession=m.createExcelRegionBindingSession;exports.excelBindingCellRange=m.excelBindingCellRange;exports.excelBindingRowRange=m.excelBindingRowRange;exports.getExcelSheetWindow=m.getExcelSheetWindow;exports.parseExcelBindingSession=m.parseExcelBindingSession;exports.parseExcelRegionBindingSession=m.parseExcelRegionBindingSession;exports.validateExcelBindingFields=m.validateExcelBindingFields;exports.validateExcelBindingRecipe=m.validateExcelBindingRecipe;exports.validateExcelBindingRegions=m.validateExcelBindingRegions;exports.validateExcelRegionBindings=m.validateExcelRegionBindings;exports.validateExcelRegionFields=m.validateExcelRegionFields;exports.validateExcelRegionGeometry=m.validateExcelRegionGeometry;exports.renderPlanToXlsx=me;
package/dist/xlsx.d.cts CHANGED
@@ -60,6 +60,10 @@ declare class Anchor implements IAnchor {
60
60
  constructor(model?: IAnchor | object);
61
61
  }
62
62
 
63
+ export declare type AnyExcelBindingDocumentResult = ExcelBindingDocumentResult | ExcelRegionBindingDocumentResult;
64
+
65
+ export declare type AnyExcelBindingSession = ExcelBindingSession | ExcelRegionBindingSession;
66
+
63
67
  declare type AutoFilter = string | {
64
68
  from: string | { row: number; column: number };
65
69
  to: string | { row: number; column: number };
@@ -471,6 +475,17 @@ export declare function createExcelBindingSession(imported: ExcelImportResult, r
471
475
  name: string;
472
476
  }): ExcelBindingSession;
473
477
 
478
+ export declare function createExcelRegionBindingDocument(imported: ExcelImportResult, recipe: ExcelRegionBindingRecipe, datasets: readonly ExcelBindingDataset[], identity: {
479
+ id: string;
480
+ name: string;
481
+ }): ExcelRegionBindingDocumentResult;
482
+
483
+ /** Draft sessions preserve exact incomplete mappings; applying still runs geometry and contract checks. */
484
+ export declare function createExcelRegionBindingSession(source: ExcelImportResult, recipe: ExcelRegionBindingRecipe, identity: {
485
+ id: string;
486
+ name: string;
487
+ }): ExcelRegionBindingSession;
488
+
474
489
  declare interface Csv {
475
490
  /**
476
491
  * read from a file
@@ -600,6 +615,15 @@ declare enum ErrorValue {
600
615
  Num = '#NUM!',
601
616
  }
602
617
 
618
+ /** Convert graphical two-dimensional selection into exact, source-bounded coordinates. */
619
+ export declare function excelBindingCellRange(imported: ExcelImportResult, sheetName: string, from: {
620
+ row: number;
621
+ column: number;
622
+ }, to?: {
623
+ row: number;
624
+ column: number;
625
+ }): string;
626
+
603
627
  export declare type ExcelBindingColumn = string | (Omit<ListColumn, "widthMm" | "header"> & {
604
628
  header?: string;
605
629
  });
@@ -845,6 +869,54 @@ declare namespace ExcelJS {
845
869
  }
846
870
  }
847
871
 
872
+ /** A row prototype is replaced, never copied into a generated business report. */
873
+ export declare interface ExcelRegionBinding {
874
+ id: string;
875
+ /** One physical source row, with any contiguous subset of the sheet columns. */
876
+ range: string;
877
+ dataset: string;
878
+ /** record accepts zero or one row; repeat expands vertically and shifts following bands. */
879
+ mode: "record" | "repeat";
880
+ fields: string[];
881
+ rowKey: string;
882
+ revisionField?: string;
883
+ sourceTokenField?: string;
884
+ /** Optional immediately preceding header, with the same physical columns. */
885
+ headerRange?: string;
886
+ }
887
+
888
+ export declare interface ExcelRegionBindingDocumentResult {
889
+ document: ReportTemplateDocument;
890
+ recipe: ExcelRegionBindingRecipe;
891
+ warnings: string[];
892
+ }
893
+
894
+ /** Version 2 describes several independent, vertically ordered data regions on one Sheet. */
895
+ export declare interface ExcelRegionBindingRecipe {
896
+ version: "2.0";
897
+ sheet: string;
898
+ regions: ExcelRegionBinding[];
899
+ /** Full-width source rows reserved on every page; excluded from flowing content. */
900
+ footerRange?: string;
901
+ }
902
+
903
+ export declare interface ExcelRegionBindingSession {
904
+ version: "2.0";
905
+ source: ExcelImportResult;
906
+ recipe: ExcelRegionBindingRecipe;
907
+ identity: {
908
+ id: string;
909
+ name: string;
910
+ };
911
+ }
912
+
913
+ export declare interface ExcelRegionBindingValidation {
914
+ ok: boolean;
915
+ issues: ExcelBindingIssue[];
916
+ mapped: number;
917
+ total: number;
918
+ }
919
+
848
920
  export declare interface ExcelSheetWindow {
849
921
  top: number;
850
922
  bottom: number;
@@ -1065,6 +1137,8 @@ declare interface GridCell {
1065
1137
  value?: string | number | boolean | null;
1066
1138
  /** Excel 数字格式(例如 #,##0.00 / 0.00%),不改变 text。 */
1067
1139
  numberFormat?: string;
1140
+ /** Physical left inset for hierarchical labels; raw value stays unchanged. */
1141
+ indentMm?: number;
1068
1142
  /** 编辑输入类型;省略时只按原始值推断,数字字符串不会被转换为数值。 */
1069
1143
  valueType?: "text" | "number" | "boolean";
1070
1144
  /** 单元格级编辑控制;预览仍需显式开启 editing。 */
@@ -1216,6 +1290,8 @@ declare interface ListColumn {
1216
1290
 
1217
1291
  declare interface ListComponent {
1218
1292
  kind: "list";
1293
+ /** Opaque serializable layout annotations; interpreted only by explicit optional adapters. */
1294
+ meta?: Record<string, unknown>;
1219
1295
  id?: string;
1220
1296
  /** 宽表标记用于连续 Excel;不改变低层列表的列宽和分页算法。 */
1221
1297
  layout?: "page" | "wide";
@@ -1225,6 +1301,10 @@ declare interface ListComponent {
1225
1301
  topMm: number;
1226
1302
  widthMm: number;
1227
1303
  dataset: string;
1304
+ /** Headerless record/region bindings do not allocate a synthetic list header. */
1305
+ header?: boolean;
1306
+ /** A fixed record region rejects multiple rows instead of dropping source data. */
1307
+ cardinality?: "record";
1228
1308
  /** 数据集中稳定业务主键的字段名;省略时编辑仅有计划内坐标。 */
1229
1309
  rowKey?: string;
1230
1310
  revisionField?: string;
@@ -1251,6 +1331,8 @@ declare interface ListComponent {
1251
1331
  computed?: ComputedField[];
1252
1332
  /** Dynamic pivot of the current source dataset, with read-only derived identities. */
1253
1333
  matrix?: MatrixTableOptions;
1334
+ /** Full ordered hierarchy; source parent values and descendant-leaf rollups are explicit. */
1335
+ tree?: TreeTableOptions;
1254
1336
  /** Explicit row visibility; hidden rows do not participate in summaries. */
1255
1337
  rowVisibleWhen?: StyleRule["when"];
1256
1338
  /** Master/detail relation is keyed by business identity, never by display row index. */
@@ -1537,6 +1619,8 @@ declare const enum PaperSize {
1537
1619
 
1538
1620
  export declare function parseExcelBindingSession(input: unknown): ExcelBindingSession;
1539
1621
 
1622
+ export declare function parseExcelRegionBindingSession(input: unknown): ExcelRegionBindingSession;
1623
+
1540
1624
  declare interface PlanComponent {
1541
1625
  /** Template page furniture repeats per page and reserves its vertical band. */
1542
1626
  pageAnchor?: "header" | "footer";
@@ -1573,6 +1657,7 @@ declare interface PlanGrid {
1573
1657
  }
1574
1658
 
1575
1659
  declare interface PlanPage {
1660
+ meta?: Record<string, unknown>;
1576
1661
  /** wide 表示完整自然列宽;页面仅为预览的垂直窗口分段。 */
1577
1662
  layout?: "page" | "wide";
1578
1663
  pageWidthMm: number;
@@ -1721,13 +1806,25 @@ declare interface ReportFieldContract {
1721
1806
  unit?: string;
1722
1807
  }
1723
1808
 
1809
+ declare interface ReportFlowBand {
1810
+ /** Exact stable component IDs. Static components use nid, lists use id. */
1811
+ componentIds: string[];
1812
+ /** Source-template coordinates; following bands keep their original gap. */
1813
+ topMm: number;
1814
+ heightMm: number;
1815
+ }
1816
+
1817
+ declare interface ReportPageFlow {
1818
+ bands: ReportFlowBand[];
1819
+ }
1820
+
1724
1821
  /** 报表参数定义(声明式,模板自描述参数面:渲染组件据此生成查询面板) */
1725
1822
  declare interface ReportParamDef {
1726
1823
  /** 参数名(传入 params,与数据集 SQL #{field} 绑定对应) */
1727
1824
  field: string;
1728
1825
  /** 显示名(缺省用 field) */
1729
1826
  label?: string;
1730
- type?: "text" | "number" | "date" | "select";
1827
+ type?: "text" | "number" | "date" | "month" | "year" | "dateRange" | "select";
1731
1828
  /** select 选项 */
1732
1829
  options?: Array<{
1733
1830
  label: string;
@@ -1736,7 +1833,7 @@ declare interface ReportParamDef {
1736
1833
  defaultValue?: string;
1737
1834
  required?: boolean;
1738
1835
  placeholder?: string;
1739
- /** 数字上下界;date 参数使用 YYYY-MM-DD 字符串(含边界)。 */
1836
+ /** 数字上下界;日期/月/年使用对应规范字符串;dateRange 对两端使用 YYYY-MM-DD 边界(含边界)。 */
1740
1837
  min?: number | string;
1741
1838
  max?: number | string;
1742
1839
  minLength?: number;
@@ -2183,6 +2280,9 @@ declare interface TemplatePage {
2183
2280
  marginLeftMm?: number;
2184
2281
  marginRightMm?: number;
2185
2282
  components: TemplateComponent[];
2283
+ /** Explicit vertical bands preserve source gaps as dynamic regions expand. */
2284
+ flow?: ReportPageFlow;
2285
+ meta?: Record<string, unknown>;
2186
2286
  }
2187
2287
 
2188
2288
  declare interface TimePeriodRuleType extends ConditionalFormattingBaseRule {
@@ -2200,6 +2300,26 @@ declare interface Top10RuleType extends ConditionalFormattingBaseRule {
2200
2300
  bottom: boolean;
2201
2301
  }
2202
2302
 
2303
+ /** A serialized tree contract. Sibling and root order follow input order. */
2304
+ declare interface TreeTableOptions {
2305
+ input: "flat" | "nested";
2306
+ idField: string;
2307
+ /** Flat roots have null/undefined parent values. */
2308
+ parentField?: string;
2309
+ /** Nested child arrays, defaults to children. Every node still needs an ID. */
2310
+ childrenField?: string;
2311
+ labelField: string;
2312
+ indentMm?: number;
2313
+ orphan?: "error" | "root";
2314
+ /** Source preserves parent values; leaf-aggregate derives only parents from descendant leaves. */
2315
+ parentValues?: "source" | "leaf-aggregate";
2316
+ aggregates?: AggregateDefinition[];
2317
+ maxRows?: number;
2318
+ maxDepth?: number;
2319
+ /** Bounded leaf-to-ancestor aggregate work; default one million. */
2320
+ maxAggregationVisits?: number;
2321
+ }
2322
+
2203
2323
  /** Contract and mapping validation does not traverse imported grids. */
2204
2324
  export declare function validateExcelBindingFields(imported: ExcelImportResult, recipe: ExcelBindingRecipe, datasets: readonly ExcelBindingDataset[]): ExcelBindingValidation;
2205
2325
 
@@ -2209,6 +2329,13 @@ export declare function validateExcelBindingRecipe(imported: ExcelImportResult,
2209
2329
  /** Region-only validation lets reactive consumers reuse the result while only mappings change. */
2210
2330
  export declare function validateExcelBindingRegions(imported: ExcelImportResult, recipe: ExcelBindingRecipe): ExcelBindingIssue[];
2211
2331
 
2332
+ export declare function validateExcelRegionBindings(imported: ExcelImportResult, recipe: ExcelRegionBindingRecipe, datasets: readonly ExcelBindingDataset[]): ExcelRegionBindingValidation;
2333
+
2334
+ export declare function validateExcelRegionFields(recipe: ExcelRegionBindingRecipe, datasets: readonly ExcelBindingDataset[]): ExcelRegionBindingValidation;
2335
+
2336
+ /** Geometry-only scan is separate so field-selection UI need not repeatedly traverse the source grid. */
2337
+ export declare function validateExcelRegionGeometry(imported: ExcelImportResult, recipe: ExcelRegionBindingRecipe): ExcelBindingIssue[];
2338
+
2212
2339
  declare enum ValueType {
2213
2340
  Null = 0,
2214
2341
  Merge = 1,