@agile-team/mach-report 2.6.1 → 2.8.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.
- package/README.md +59 -8
- package/dist/ReportPreview-BKKDAv8e.js +4481 -0
- package/dist/ReportPreview-E3cm67Tk.cjs +6 -0
- package/dist/{assets-NVA_sftu.js → assets-B9qJku3V.js} +54 -57
- package/dist/assets-RZan7EyL.cjs +1 -0
- package/dist/capabilities-joSutDF8.js +63 -0
- package/dist/capabilities-xGTpnPjJ.cjs +1 -0
- package/dist/designer.cjs +1 -1
- package/dist/designer.d.cts +922 -753
- package/dist/designer.d.ts +922 -753
- package/dist/designer.js +490 -234
- package/dist/index.cjs +8 -8
- package/dist/index.d.cts +128 -3
- package/dist/index.d.ts +128 -3
- package/dist/index.js +971 -699
- package/dist/pdf.cjs +30 -30
- package/dist/pdf.d.cts +11 -3
- package/dist/pdf.d.ts +11 -3
- package/dist/pdf.js +1501 -1500
- package/dist/{plugin-Ds10VnQO.js → plugin-PCgxBVB2.js} +1 -1
- package/dist/{plugin-BqBkn_kI.cjs → plugin-mAfvgSey.cjs} +1 -1
- package/dist/progress-DD964VAB.js +102 -0
- package/dist/progress-KvhwXZ1Q.cjs +1 -0
- package/dist/{report-source-B9bENO0F.js → report-source-BXHNy_AD.js} +337 -332
- package/dist/report-source-CCAvFE3t.cjs +1 -0
- package/dist/server/node.d.cts +26 -3
- package/dist/server/node.d.ts +26 -3
- package/dist/server-node.cjs +1 -1
- package/dist/server-node.js +125 -92
- package/dist/server.cjs +1 -1
- package/dist/server.d.cts +28 -3
- package/dist/server.d.ts +28 -3
- package/dist/server.js +172 -164
- package/dist/style.css +1 -1
- package/dist/task-events-DQ276fn2.cjs +1 -0
- package/dist/task-events-Dpsvf_t2.js +47 -0
- package/dist/vue/async.d.cts +1553 -2083
- package/dist/vue/async.d.ts +1553 -2083
- package/dist/vue/index.d.cts +2465 -3310
- package/dist/vue/index.d.ts +2465 -3310
- package/dist/vue-async.cjs +1 -1
- package/dist/vue-async.js +3 -3
- package/dist/vue.cjs +1 -1
- package/dist/vue.js +159 -132
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +26 -3
- package/dist/worker.d.ts +26 -3
- package/dist/worker.js +110 -85
- package/dist/xlsx.cjs +14 -14
- package/dist/xlsx.d.cts +11 -3
- package/dist/xlsx.d.ts +11 -3
- package/dist/xlsx.js +656 -652
- package/package.json +2 -2
- package/dist/ReportPreview-Dk-28QAi.js +0 -2946
- package/dist/ReportPreview-FSvcBLjH.cjs +0 -6
- package/dist/assets-66UBlhES.cjs +0 -1
- package/dist/capabilities-CNjIirfo.js +0 -36
- package/dist/capabilities-D4xeVYSR.cjs +0 -1
- package/dist/grid-geometry-BNptEcMm.js +0 -65
- package/dist/grid-geometry-CZ_cYB6O.cjs +0 -1
- package/dist/report-source-BbNkkBDy.cjs +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const T=require("./render-plan-CckPEQyf.cjs"),A=require("./textwrap-CnGsEum6.cjs"),x=require("./style-CpwiOPyB.cjs"),ae=require("./validate-DfHPD8wX.cjs"),ie=require("./report-params-CjWrjPl6.cjs"),B=require("./template-registry-DWExx0gU.cjs"),j=require("./param-validation-CiTxFeZ8.cjs"),se=require("./task-events-DQ276fn2.cjs");function K(e){if(!e||e.kind==="date")return;const t=e.digits;if(!(t!==void 0&&(!Number.isInteger(t)||t<0||t>100))){if(e.kind==="percent"){const r=t??2;return`0${r?`.${"0".repeat(r)}`:""}%`}return t===void 0?e.thousands?"#,##0.###############":void 0:`${e.thousands?"#,##0":"0"}${t?`.${"0".repeat(t)}`:""}`}}function Y(e){const t=/^(\d{4})[-/](\d{1,2})[-/](\d{1,2})$/.exec(e.trim());if(t){const n=new Date(Number(t[1]),Number(t[2])-1,Number(t[3]));return Number.isNaN(n.getTime())?null:n}const r=new Date(e);return Number.isNaN(r.getTime())?null:r}function I(e,t){return e.toLocaleString("en-US",{minimumFractionDigits:t,maximumFractionDigits:t})}function me(e,t){const r=n=>String(n).padStart(2,"0");return t.replace(/YYYY/g,String(e.getFullYear())).replace(/MM/g,r(e.getMonth()+1)).replace(/DD/g,r(e.getDate())).replace(/hh/g,r(e.getHours())).replace(/mm/g,r(e.getMinutes())).replace(/ss/g,r(e.getSeconds()))}function ce(e,t,r){return r!=null?t?I(e,r):e.toFixed(r):t?I(e):String(e)}function F(e){const t=typeof e=="number"?e:Number(String(e).replace(/,/g,""));return Number.isFinite(t)?t:null}function q(e,t){if(e==null||e===""||!t)return String(e??"");switch(t.kind){case"number":{const r=F(e);return r==null?String(e):ce(r,t.thousands===!0,t.digits)}case"percent":{const r=F(e);return r==null?String(e):`${I(r*100,t.digits??2)}%`}case"date":{const r=t.pattern??"YYYY-MM-DD",n=e instanceof Date?e:Y(String(e));return n?me(n,r):String(e)}default:return String(e)}}function V(e,t){const r=e[t.field];if(r==null||r==="")return!1;if(typeof t.value=="number"){const i=F(r);if(i==null)return!1;switch(t.op){case">":return i>t.value;case">=":return i>=t.value;case"<":return i<t.value;case"<=":return i<=t.value;case"==":return i===t.value;case"!=":return i!==t.value}}const n=String(r),o=String(t.value);switch(t.op){case"==":return n===o;case"!=":return n!==o;case">":return n>o;case">=":return n>=o;case"<":return n<o;case"<=":return n<=o}return!1}const ue=["text","number","boolean","date","decimal"],le=new Set(["__proto__","prototype","constructor"]);function v(e){throw new Error(`数据契约无效:${e}`)}function J(e){(!e||!Array.isArray(e.fields)||!e.fields.length||e.fields.length>2048)&&v("fields 应包含 1–2048 个字段");const t=new Set;for(const r of e.fields)(!r||typeof r.field!="string"||!r.field.trim()||le.has(r.field)||t.has(r.field))&&v("字段名应安全、非空且唯一"),t.add(r.field),ue.includes(r.type)||v(`未知字段类型 ${r.type}`),he(r),fe(r),de(r);ge(e,t)}function de(e){e.enum!==void 0&&(!Array.isArray(e.enum)||!e.enum.length||e.enum.some(t=>!U(t,e.type)))&&v("enum 应为匹配字段类型的非空标量数组")}function ge(e,t){e.rowKey!==void 0&&((typeof e.rowKey!="string"||!e.rowKey.trim()||!t.has(e.rowKey))&&v("rowKey 应为引用已声明字段的非空字符串"),e.fields.find(r=>r.field===e.rowKey)?.type==="boolean"&&v("布尔字段不能作为业务主键"))}function fe(e){for(const t of["label","unit"])e[t]!==void 0&&typeof e[t]!="string"&&v(`${t} 应为字符串`);for(const t of["required","nullable"])e[t]!==void 0&&typeof e[t]!="boolean"&&v(`${t} 应为布尔值`);e.semanticRole!==void 0&&!["identifier","dimension","measure","date","text"].includes(e.semanticRole)&&v("未知字段语义")}function he(e){for(const t of["min","max","minLength","maxLength"]){const r=e[t];r!==void 0&&(!Number.isFinite(r)||t.includes("Length")&&(!Number.isInteger(r)||r<0))&&v(`${t} 无效`)}e.min!==void 0&&e.max!==void 0&&e.min>e.max&&v("min 不能超过 max"),e.minLength!==void 0&&e.maxLength!==void 0&&e.minLength>e.maxLength&&v("minLength 不能超过 maxLength"),e.type!=="number"&&(e.min!==void 0||e.max!==void 0)&&v("min/max 仅适用于 number,精确小数文本需业务校验"),["number","boolean"].includes(e.type)&&(e.minLength!==void 0||e.maxLength!==void 0)&&v("长度约束仅适用于文本类型")}function pe(e){const t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);if(!t)return!1;const r=Number(t[1]),n=Number(t[2]),o=Number(t[3]),i=r%4===0&&(r%100!==0||r%400===0);return r>0&&n>=1&&n<=12&&o>=1&&o<=[31,i?29:28,31,30,31,30,31,31,30,31,30,31][n-1]}function U(e,t){return t==="number"?typeof e=="number"&&Number.isFinite(e):t==="boolean"?typeof e=="boolean":typeof e!="string"?!1:t==="date"?pe(e):t==="decimal"?e.length<=1e4&&/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/.test(e):!0}function ye(e,t){if(e==null)return t.required||e===null&&t.nullable===!1?{code:"required",message:"缺少必需字段值"}:void 0;if(!U(e,t.type))return{code:"type",message:`值应为 ${t.type},不会自动转换原始值`};if(t.enum&&!t.enum.includes(e))return{code:"enum",message:"值不在允许的枚举中"};if(typeof e=="number"&&(t.min!==void 0&&e<t.min||t.max!==void 0&&e>t.max))return{code:"range",message:"数值超出范围"};if(typeof e=="string"&&!we(e,t))return{code:"range",message:"文本长度超出范围"}}function we(e,t){if(t.minLength===void 0&&t.maxLength===void 0)return!0;let r=0;for(const n of e)r++;return(t.minLength===void 0||r>=t.minLength)&&(t.maxLength===void 0||r<=t.maxLength)}function D(e,t){const r=e??t;if(!Number.isInteger(r)||r<1)throw new Error("数据校验预算应为正整数");return r}function be(e,t,r){const n=Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;if((typeof n!="string"||!n.trim())&&!(typeof n=="number"&&Number.isFinite(n)))return"业务主键应为非空字符串或有限数字";const o=JSON.stringify([typeof n,n]);if(r.has(o))return"业务主键重复";r.add(o)}function Q(e,t,r={}){J(t);const n=r.path??"$.rows",o=[],i=D(r.maxIssues,100);if(!Array.isArray(e))return{ok:!1,issues:[{code:"row",path:n,message:"数据集应为对象数组"}]};if(e.length>D(r.maxRows,1e5)||e.length*t.fields.length>D(r.maxCells,2e6))return{ok:!1,issues:[{code:"budget",path:n,message:"数据校验超出行数或单元格预算"}]};const a=new Set;for(let s=0;s<e.length&&o.length<i;s++){const d=e[s];if(!d||typeof d!="object"||Array.isArray(d)){o.push({code:"row",path:`${n}[${s}]`,rowIndex:s,message:"行应为对象"});continue}Me(d,t,s,n,a,o,i)}return{ok:o.length===0,issues:o}}function Me(e,t,r,n,o,i,a){for(const s of t.fields){if(i.length>=a)return;const d=ye(Object.prototype.hasOwnProperty.call(e,s.field)?e[s.field]:void 0,s);d&&i.push({...d,rowIndex:r,field:s.field,path:`${n}[${r}].${s.field}`})}if(t.rowKey&&i.length<a){const s=be(e,t.rowKey,o);s&&i.push({code:"row-key",path:`${n}[${r}].${t.rowKey}`,message:s,rowIndex:r,field:t.rowKey})}}function Se(e){return J(e),{$schema:"https://json-schema.org/draft/2020-12/schema",type:"array",items:{type:"object",properties:Object.fromEntries(e.fields.map(r=>[r.field,ve(r,r.field===e.rowKey)])),required:e.fields.filter(r=>r.required||r.field===e.rowKey).map(r=>r.field),additionalProperties:!0},...e.rowKey?{"x-report-rowKey":e.rowKey}:{}}}function ve(e,t){const r=!t&&e.nullable!==!1&&!e.required;return{type:r?[W(e.type),"null"]:W(e.type),...e.label?{title:e.label}:{},...e.type==="date"?{format:"date"}:{},...e.type==="decimal"?{pattern:"^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$"}:{},...e.enum?{enum:r?[...e.enum,null]:[...e.enum]}:{},...e.min===void 0?{}:{minimum:e.min},...e.max===void 0?{}:{maximum:e.max},...xe(e,t),...t&&e.type==="text"?{pattern:"\\S"}:{},...e.unit?{"x-report-unit":e.unit}:{},...e.semanticRole?{"x-report-semanticRole":e.semanticRole}:{}}}function xe(e,t){const r={};return(e.minLength!==void 0||t&&e.type!=="number")&&(r.minLength=Math.max(e.minLength??0,t?1:0)),e.type==="decimal"?r.maxLength=Math.min(e.maxLength??1e4,1e4):e.maxLength!==void 0&&(r.maxLength=e.maxLength),r}function W(e){return e==="text"||e==="date"||e==="decimal"?"string":e}class E extends Error{constructor(t,r){super(`报表页数超出上限 ${t}(至少 ${r} 页)`),this.limit=t,this.actual=r,this.code="page-limit",this.name="PaginatePageLimitError"}}function Pe(e){return{widthMm:e.widthMm,heightMm:e.heightMm,marginTopMm:e.marginTopMm??0,marginBottomMm:e.marginBottomMm??0,marginLeftMm:e.marginLeftMm??0,marginRightMm:e.marginRightMm??0,components:[]}}function $e(e,t){return t.heightMm-(e.layout==="wide"?t.marginBottomMm:e.marginBottomMm??t.marginBottomMm)}function X(e){if(e==null)return"";if(typeof e=="string")return e;if(typeof e=="number")return String(e);if(typeof e=="boolean")return e?"是":"否";if(e instanceof Date)return e.toISOString().slice(0,10);try{return JSON.stringify(e)}catch{return String(e)}}function Z(e,t){let r=e.textMetrics.get(t);if(!r){const n=x.resolveFontSize(t).fontSizePt;r={measureOptions:{fontSizePt:n,fontFamily:t.fontFamily??T.DEFAULT_FONT_FAMILY,italic:t.italic,bold:t.bold,letterSpacingPt:t.letterSpacing},lineMm:n*(t.lineHeight??T.LINE_HEIGHT)*25.4/72},e.textMetrics.set(t,r)}return r}function ee(e,t,r){return r==="identifier"||r==="dimension"||r==="date"?"center":r==="measure"?"right":r==="text"?"left":t?.kind==="number"||t?.kind==="percent"?"right":t?.kind==="date"||e instanceof Date||typeof e=="boolean"?"center":typeof e=="number"&&Number.isFinite(e)?"right":"left"}function ke(e){if(e===null||typeof e=="string"||typeof e=="boolean"||typeof e=="number"&&Number.isFinite(e))return e}function Re(e,t){const r=e.fontSizePt??T.DEFAULT_FONT_PT,n=e.paddingMm??1,o=e.columns.map(m=>m.align??m.style?.align??e.align??"left"),i=e.columns.map((m,u)=>({...x.mergeComponentStyles({fontSize:r,verticalAlign:"middle"},m.style),align:o[u]==="auto"?"left":o[u]})),a=i.map((m,u)=>o[u]==="auto"?{left:m,center:{...m,align:"center"},right:{...m,align:"right"}}:void 0),s=e.columns.map((m,u)=>m.rules?.map(b=>{const P=a[u];if(P)return{left:x.mergeComponentStyles(P.left,b.style),center:x.mergeComponentStyles(P.center,b.style),right:x.mergeComponentStyles(P.right,b.style)};const k=x.mergeComponentStyles(i[u],b.style);return{left:k,center:k,right:k}})),d=e.columns.map(m=>{let u=x.mergeComponentStyles({fontSize:r,bold:e.headerBold??!0,align:"center",verticalAlign:"middle",backgroundColor:e.headerBackgroundColor},m.style);return e.headerAlign!==void 0&&(u.align=e.headerAlign),u=x.mergeComponentStyles(u,e.headerStyle),m.headerAlign!==void 0&&(u.align=m.headerAlign),x.mergeComponentStyles(u,m.headerStyle)}),f=e.columns.map(m=>m.header);let c=e.rowHeightMm??0;for(let m=0;m<f.length;m++){const u=d[m],b=x.resolveFontSize(u).fontSizePt,P=A.wrapText(f[m],e.columns[m].widthMm-n*2,{fontSizePt:b,fontFamily:u.fontFamily??T.DEFAULT_FONT_FAMILY,italic:u.italic,bold:u.bold,letterSpacingPt:u.letterSpacing},t),k=b*(u.lineHeight??T.LINE_HEIGHT)*25.4/72;c=Math.max(c,Math.max(P.length,1)*k+n*2)}const g=f.map((m,u)=>({text:m,style:d[u]})),w=e.border===!1?{borderTop:!1,borderRight:!1,borderBottom:!1,borderLeft:!1}:{borderBottom:!0,borderLeft:!0,borderRight:!0,borderTop:!0},p=e.columns.map(m=>m.widthMm),h=Te(e.headerGrid,p,{cells:[g],colWidthsMm:p,rowHeightsMm:[c],paddingMm:n});return{fontSizePt:r,paddingMm:n,cellStyles:i,autoStyles:a,ruleStyles:s,textMetrics:new WeakMap,numberFormats:e.columns.map(m=>K(m.format)),borderStyle:w,headerHeightMm:h.rowHeightsMm.reduce((m,u)=>m+u,0),headerGrid:h,colWidthsMm:p,columns:e.columns}}function Te(e,t,r){if(!e)return r;if(!e.cells.length)throw new Error("自定义列表表头至少需要一行");const n=e.rowHeightsMm??e.cells.map(()=>r.rowHeightsMm[0]);if(n.length!==e.cells.length||n.some(o=>!Number.isFinite(o)||o<=0))throw new Error("自定义列表表头行高无效");return{...e,colWidthsMm:t,rowHeightsMm:n}}function Le(e,t,r){const n=t.format?.kind==="number"||t.format?.kind==="percent";t.valueType!==void 0?e.valueType=t.valueType:n&&(e.valueType="number"),t.editable!==void 0&&(e.editable=t.editable),(typeof e.value=="number"||e.value==null)&&r!==void 0&&(e.numberFormat=r)}function z(e,t,r){const n=e.columns;let o=e.rowHeightFloorMm;const i=new Array(n.length);for(let a=0;a<n.length;a++){const s=n[a],d=t[s.field],f=e.autoStyles[a]?ee(d,s.format,s.semanticRole):"left";let c=e.autoStyles[a]?.[f]??e.cellStyles[a];if(s.rules)for(let u=0;u<s.rules.length;u++){const b=s.rules[u];if(V(t,b.when)){c=e.ruleStyles[a][u][f];break}}const g=s.format?q(d,s.format):X(d),w=Z(e,c),p=A.wrapText(g,s.widthMm-e.paddingMm*2,w.measureOptions,r);o=Math.max(o,p.length*w.lineMm+e.paddingMm*2);const h=ke(d),m={text:g,style:c};h!==void 0&&(m.value=h),Le(m,s,e.numberFormats[a]),i[a]=m}return{grid:{cells:[i],colWidthsMm:e.colWidthsMm,rowHeightsMm:[o],paddingMm:e.paddingMm},heightMm:o}}function*Ee(e,t){if(!t){for(const n of e)yield{kind:"row",row:n};return}const r=new Map;for(const n of e){const o=X(n[t.field]),i=r.get(o);i?i.push(n):r.set(o,[n])}for(const[n,o]of r){yield{kind:"groupHeader",label:(t.headerTemplate??"{value}").replace(/\{value\}/g,n),firstRow:o[0]};for(const i of o)yield{kind:"row",row:i};t.subtotal?.length&&(yield{kind:"subtotal",label:t.subtotalLabel??"小计",rows:o})}}function Ne(e,t){let r=0;for(const n of e){const o=typeof n[t]=="number"?n[t]:Number(n[t]);Number.isFinite(o)&&(r+=o)}return r}function te(e,t,r){return new Map(r.map(n=>{const o=e.find(a=>a.field===n)?.format??{kind:"number",thousands:!0},i=Ne(t,n);return[n,{text:q(i,o),value:i,numberFormat:K(o)}]}))}function re(e,t){const r=e.findIndex(n=>t.includes(n.field));return r>0?r:1}function C(e,t,r,n,o,i){const a=[],s=Math.max(1,Math.min(i,e.columns.length)),d=x.mergeComponentStyles({fontSize:e.fontSizePt},o);a.push({text:r,colSpan:s,style:{bold:!0,...d}});for(let g=s;g<e.columns.length;g++){const w=e.columns[g],p=n.get(w.field),h=e.autoStyles[g]?.[ee(p?.value,w.format)]??e.cellStyles[g];a.push({...p,text:p?.text??"",style:x.mergeComponentStyles(h,o)})}let f=e.rowHeightFloorMm,c=0;for(const g of a){let w=0;const p=c+(g.colSpan??1);for(;c<p;c++)w+=e.colWidthsMm[c]??0;const h=Z(e,g.style),m=A.wrapText(g.text??"",w-e.paddingMm*2,h.measureOptions,t);f=Math.max(f,m.length*h.lineMm+e.paddingMm*2)}return{grid:{cells:[a],colWidthsMm:e.colWidthsMm,rowHeightsMm:[f],paddingMm:e.paddingMm},heightMm:f}}function Fe(e,t,r){const{templatePage:n,current:o,warnings:i,nextId:a,pushCurrent:s}=r,d=()=>$e(n,o),f=o.marginTopMm,c={id:r.tableId,columnKeys:e.columns.map(l=>l.field),...e.layout===void 0?{}:{layout:e.layout},...e.title===void 0?{}:{title:e.title}};let g=0;const w={kind:"rect",leftMm:e.leftMm,topMm:0,widthMm:e.widthMm,heightMm:t.headerHeightMm,grid:t.headerGrid,nid:a("listh"),table:{...c,role:"header",rowIndex:-1},style:t.borderStyle},p=l=>o.components.push({...w,topMm:l});let h=e.topMm;p(h),h+=t.headerHeightMm+r.mmPerRow;function m(){const l=n.layout==="wide"?0:e.topMm;return e.headerEveryPage!==!1?l+t.headerHeightMm:n.layout==="wide"?0:f}function u(){const l=n.layout==="wide"?0:o.marginBottomMm;return n.heightMm-l-m()}function b(l){if(h+l<=d())return;s(),o.components=[],o.heightMm=n.heightMm,n.layout==="wide"&&(o.marginTopMm=0,o.marginBottomMm=0);const M=n.layout==="wide"?0:e.topMm;e.headerEveryPage!==!1?(p(M),h=M+t.headerHeightMm):h=n.layout==="wide"?0:f}function P(l,M,S,R){const L=u();l.heightMm>L&&i.push(`列表 ${e.id??e.dataset} 行高 ${l.heightMm.toFixed(2)}mm 超出单页可用高度 ${L.toFixed(2)}mm,预览与打印可能截断内容`),b(l.heightMm),o.components.push({kind:"rect",leftMm:e.leftMm,topMm:h,widthMm:e.widthMm,heightMm:l.heightMm,grid:l.grid,nid:a(M),table:{...c,role:S,rowIndex:g++,...R?{source:R}:{}},style:t.borderStyle}),h+=l.heightMm}function k(l){l<=u()&&b(l)}return{keepTogether:k,placeGridRow:P}}function Ae(e,t){if(!e.rowKey)return;const r=t[e.rowKey];if((typeof r!="string"||!r.trim())&&!(typeof r=="number"&&Number.isFinite(r)))throw new Error(`数据集 ${e.dataset} 的 ${e.rowKey} 应为稳定的字符串或有限数字主键`);const n=e.revisionField?t[e.revisionField]:void 0,o=e.sourceTokenField?t[e.sourceTokenField]:void 0;if(n!==void 0&&typeof n!="string"&&!(typeof n=="number"&&Number.isFinite(n)))throw new Error("业务修订号应为字符串或有限数字");if(o!==void 0&&typeof o!="string")throw new Error("来源令牌应为字符串");return{datasetId:e.dataset,rowKey:r,...n===void 0?{}:{revision:n},...o===void 0?{}:{sourceToken:o}}}function He(e,t){const r=new Map;if(!e.rowKey)return r;const n=new Set;for(const o of t){const i=Ae(e,o),a=JSON.stringify(i.rowKey);if(n.has(a))throw new Error(`数据集 ${e.dataset} 的业务主键重复:${String(i.rowKey)}`);n.add(a),r.set(o,i)}return r}function De(e,t,r,n,o){if(!e.grandTotal)return;const i=typeof e.grandTotal=="object"?e.grandTotal:void 0,a=i?.fields??e.groupBy?.subtotal??[];if(a.length===0){n.warnings.push(`列表 ${e.id??""} 配置了 grandTotal 但未提供合计字段(groupBy.subtotal 或 grandTotal.fields)`);return}const s=C(r,n.measurer,i?.label??"合计",te(e.columns,t,a),i?.style??{},re(e.columns,a));o.placeGridRow(s,"listgt","grand-total")}function Ie(e,t,r){const n=He(e,t),o=e.columns.reduce((c,g)=>c+g.widthMm,0),i=o>e.widthMm?e.widthMm/o:1,a=i===1?e:{...e,columns:e.columns.map(c=>({...c,widthMm:c.widthMm*i}))},s={...Re(a,r.measurer),rowHeightFloorMm:a.rowHeightMm??0},d=Fe(a,s,r);let f;for(const c of Ee(t,a.groupBy))if(c.kind==="row")d.placeGridRow(f??z(s,c.row,r.measurer),"listr","body",n.get(c.row)),f=void 0;else if(c.kind==="groupHeader"){const g=C(s,r.measurer,c.label,new Map,a.groupBy?.headerStyle??{},a.columns.length);f=z(s,c.firstRow,r.measurer),a.groupBy?.keepWithNext!==!1&&d.keepTogether(g.heightMm+f.heightMm),d.placeGridRow(g,"listg","group-header")}else{const g=a.groupBy?.subtotal??[],w=C(s,r.measurer,c.label,te(a.columns,c.rows,g),a.groupBy?.subtotalStyle??{},re(a.columns,g));d.placeGridRow(w,"listst","subtotal")}De(a,t,s,r,d)}function G(e){return e.kind==="text"&&typeof e.text=="string"&&(e.text.includes("{page}")||e.text.includes("{totalPages}"))}function Ce(e,t,r,n,o,i){const a={pageWidthMm:t.widthMm,pageHeightMm:t.heightMm,...e.layout===void 0?{}:{layout:e.layout},marginTopMm:t.marginTopMm,marginBottomMm:t.marginBottomMm,marginLeftMm:t.marginLeftMm,marginRightMm:t.marginRightMm,components:t.components};n.push(a);for(const s of r){const d={...s,text:String(s.text??"").replace(/\{page\}/g,String(n.length))};a.components.push(d),d.text.includes("{totalPages}")&&o.push(d)}if(e.layout==="wide"){const s=a.components.reduce((d,f)=>Math.max(d,f.topMm+f.heightMm),0);a.marginBottomMm=i?e.marginBottomMm??0:0,a.pageHeightMm=Math.max(1,s+a.marginBottomMm)}}function ne(e,t,r={}){const n=typeof r=="number"?{mmPerRow:r}:r;if(n.maxPages!==void 0&&(!Number.isSafeInteger(n.maxPages)||n.maxPages<1))throw new RangeError("maxPages 应为正安全整数");const o=[],i=[],a=[];let s=0;const d=f=>`${f}_${(++s).toString(36)}`;for(const[f,c]of e.pages.entries()){const g=Pe(c),w=c.components.filter(G),p=(h=!1)=>{if(n.maxPages!==void 0&&i.length>=n.maxPages)throw new E(n.maxPages,i.length+1);Ce(c,g,w,i,a,h)};for(const[h,m]of c.components.entries()){if(G(m))continue;if(m.kind!=="list"){g.components.push(m);continue}const u=t[m.dataset];Array.isArray(u)||o.push(`数据集 ${m.dataset} 未提供数据,列表 ${m.id??""} 输出为空`),Ie(m,Array.isArray(u)?u:[],{templatePage:c,current:g,warnings:o,nextId:d,pushCurrent:p,measurer:n.measurer??A.heuristicMeasurer,mmPerRow:n.mmPerRow??0,tableId:`table:${f}:${h}`})}p(!0)}for(const f of a)f.text=f.text.replace(/\{totalPages\}/g,String(i.length));return{plan:{schemaVersion:T.RENDER_PLAN_SCHEMA_VERSION,pages:i},warnings:o}}function Oe(e){if(!("mapData"in e))return e;const{load:t,mapData:r,...n}=e;return{...n,load:async o=>{const i=await t(o);$(o.signal);try{return r(i,o)}catch(a){throw new y("validate",`报表 ${o.reportId} 数据映射失败`,a)}}}}class y extends Error{constructor(t,r,n){super(r),this.name="ReportSourceError",this.code=t,this.cause=n}}function H(e){const t=new Error("报表加载已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e.reason}),t}function $(e){if(e?.aborted)throw H(e)}function O(e,t){return t?new Promise((r,n)=>{const o=()=>t.removeEventListener("abort",i),i=()=>{o(),n(H(t))};t.addEventListener("abort",i,{once:!0}),t.aborted&&i(),Promise.resolve(e).then(a=>{o(),r(a)},a=>{o(),n(a)})}):Promise.resolve(e)}function Ke(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new y("validate",`报表 ${t} 的数据集应为对象`);for(const[r,n]of Object.entries(e))if(!Array.isArray(n)||n.some(o=>!o||typeof o!="object"||Array.isArray(o)))throw new y("validate",`报表 ${t} 的数据集 ${r} 应为对象数组`)}async function qe(e,t,r){const{reportId:n,signal:o}=t;try{const i=await O(e(t),o);$(o);const a=B.validateReportTemplate(i);if(!a.ok)throw new y("validate",`报表 ${n} 模板校验失败:${a.errors.slice(0,3).map(s=>`${s.path}: ${s.message}`).join("; ")}`);return r.push(...a.warnings.map(s=>`${n}: ${s.path}: ${s.message}`)),i}catch(i){throw o?.aborted?H(o):i instanceof y?i:i instanceof B.ReportTemplateError?new y("validate",`报表 ${n} 模板校验失败:${i.message}`,i):new y("fetch",`报表 ${n} 模板加载失败:${i instanceof Error?i.message:String(i)}`,i)}}async function _e(e,t,r,n){const o=t.signal;let i;try{if(e.load)i=await O(e.load(t),o);else if(e.provider){const a=await O(e.provider.query(t),o);$(o),Be(a,r),i=a.datasets,n?.(r,a)}else i=e.datasets??{}}catch(a){throw o?.aborted?H(o):a instanceof y?a:new y("fetch",`报表 ${r} 取数失败:${a instanceof Error?a.message:String(a)}`,a)}return $(o),i}function Be(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new y("validate",`报表 ${t} Provider 应返回 datasets 结果对象`);for(const r of["revision","sourceToken"])if(e[r]!==void 0&&typeof e[r]!="string")throw new y("validate",`报表 ${t} Provider ${r} 应为字符串`);if(e.diagnostics!==void 0&&(!Array.isArray(e.diagnostics)||e.diagnostics.some(r=>!r||typeof r.code!="string"||typeof r.message!="string"||!["info","warning","error"].includes(r.severity))))throw new y("validate",`报表 ${t} Provider diagnostics 不符合结构化诊断契约`)}function je(e,t,r){for(const[n,o]of Object.entries(e.dataSchema??{})){let i;try{i=Q(Object.prototype.hasOwnProperty.call(t,n)?t[n]:void 0,o,{...e.dataValidation,path:`$.datasets.${n}`})}catch(a){throw new y("config",`报表 ${r} 数据集 ${n} 字段契约配置无效`,a)}if(!i.ok)throw new y("validate",`报表 ${r} 数据集 ${n} 不符合字段契约:${i.issues[0]?.message}`,{issues:i.issues})}}function We(e,t,r,n,o){const i=o?o.maxPages-o.usedPages:void 0;try{if(i!==void 0&&i<1&&e.pages.length)throw new E(0,1);const a=i===void 0?r.pagination:{...r.pagination,maxPages:Math.max(1,Math.min(i,r.pagination?.maxPages??i))};return ne(e,t,a)}catch(a){const s=a instanceof E&&o&&a.limit===i?new E(o.maxPages,o.usedPages+a.actual):a;throw new y("validate",`报表 ${n} 排版失败:${s instanceof Error?s.message:String(s)}`,s)}}function ze(e,t,r,n){const o=new Map,i=a=>{let s=o.get(a);return s===void 0&&(s=JSON.stringify([r,n,a]),o.set(a,s)),s};for(const a of t.pages)e.push({...a,components:a.components.map(s=>s.table?{...s,table:{...s.table,id:i(s.table.id)}}:s)})}function Ge(e,t={}){if(t.maxPages!==void 0&&(!Number.isSafeInteger(t.maxPages)||t.maxPages<1))throw new y("config","maxPages 应为正安全整数");function r(o){const i=Object.prototype.hasOwnProperty.call(e,o)?e[o]:void 0;if(!i)throw new y("config",`未注册报表 ${o}`);return i}return Object.assign(async({reportIds:o,params:i,signal:a,onWarning:s,onQueryResult:d,...f})=>{$(a);const c=se.createReportTaskReporter({...f,signal:a}),g=[...o],w={...i};if(g.length===0)throw new y("config","缺少报表 ID");const p=g.map(r),h=c.runSync("validate",()=>p.map(l=>j.assertReportParams(l.params??(typeof l.template=="function"?[]:l.template.params)??[],w))),m=[],u=[];for(const[l,M]of p.entries()){$(a);const S=g[l],R={reportId:S,params:h[l],signal:a},L=typeof M.template=="function"?await c.run("query",()=>qe(M.template,R,u),S):M.template;R.params=c.runSync("validate",()=>j.assertReportParams(M.params??L.params??[],R.params),S);const N=await c.run("query",()=>_e(M,R,S,d),S);c.runSync("validate",()=>{Ke(N,S),t.onDatasets?.(S,N,L),je(M,N,S)},S),$(a);const _=c.runSync("layout",()=>We(L,N,M,S,t.maxPages===void 0?void 0:{maxPages:t.maxPages,usedPages:m.length}),S);ze(m,_.plan,l,S),u.push(..._.warnings.map(oe=>`${S}: ${oe}`))}$(a);const b={schemaVersion:T.RENDER_PLAN_SCHEMA_VERSION,pages:m},P=c.runSync("validate",()=>{const l=ae.validateRenderPlan(b);if(!l.ok)throw new y("validate",`渲染计划校验失败:${l.errors.slice(0,3).map(M=>`${M.path}: ${M.message}`).join("; ")}`);return l});u.push(...P.warnings.map(l=>`${l.path}: ${l.message}`));const k=s??t.onWarning??(l=>console.warn("[mach-report]",l));for(const l of u)$(a),k(l);return $(a),b},{getParamDefs:o=>ie.getReportParamDefs(e,o)})}exports.PaginatePageLimitError=E;exports.ReportSourceError=y;exports.createReportSource=Ge;exports.datasetJsonSchema=Se;exports.defineReport=Oe;exports.evalStyleRule=V;exports.formatValue=q;exports.paginateTemplate=ne;exports.parseDateLocal=Y;exports.toExcelNumberFormat=K;exports.toNumber=F;exports.validateDatasetRows=Q;
|
package/dist/server/node.d.cts
CHANGED
|
@@ -212,12 +212,14 @@ declare interface ReportRuntime {
|
|
|
212
212
|
|
|
213
213
|
/** 可用 worker_threads/进程/RPC 实现;接收可序列化请求,signal 由桥接层映射为取消消息。 */
|
|
214
214
|
declare interface ReportRuntimeExecutor {
|
|
215
|
-
prepare(input: Omit<ReportRuntimeInput, "signal">, signal?: AbortSignal): Promise<PreparedReport>;
|
|
216
|
-
export(input: Omit<ReportRuntimeExportInput, "signal">, signal?: AbortSignal): Promise<ReportRuntimeExportResult>;
|
|
215
|
+
prepare(input: Omit<ReportRuntimeInput, "signal" | "onEvent">, signal?: AbortSignal, onEvent?: ReportTaskObserver): Promise<PreparedReport>;
|
|
216
|
+
export(input: Omit<ReportRuntimeExportInput, "signal" | "onEvent">, signal?: AbortSignal, onEvent?: ReportTaskObserver): Promise<ReportRuntimeExportResult>;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
declare interface ReportRuntimeExportInput extends ReportRuntimeInput {
|
|
220
220
|
format: "pdf" | "xlsx";
|
|
221
|
+
/** strict 在编码前拒绝已识别的输出降级;默认保留诊断并继续。 */
|
|
222
|
+
fidelity?: "warn" | "strict";
|
|
221
223
|
/** PDF 中文需宿主显式提供有授权的字体;不隐式下载字体或资源。 */
|
|
222
224
|
pdf?: {
|
|
223
225
|
customFontBytes?: Uint8Array | ArrayBuffer;
|
|
@@ -242,7 +244,7 @@ declare interface ReportRuntimeExportResult extends Omit<PreparedReport, "plan">
|
|
|
242
244
|
contentType: string;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
declare interface ReportRuntimeInput {
|
|
247
|
+
declare interface ReportRuntimeInput extends ReportTaskMonitoring {
|
|
246
248
|
reportIds: string[];
|
|
247
249
|
params?: Record<string, string>;
|
|
248
250
|
signal?: AbortSignal;
|
|
@@ -256,10 +258,30 @@ declare interface ReportRuntimeStats {
|
|
|
256
258
|
outputBytes?: number;
|
|
257
259
|
}
|
|
258
260
|
|
|
261
|
+
/** 阶段事件只包含可序列化值;不表示估算百分比,也不包含业务数据。 */
|
|
262
|
+
declare interface ReportTaskEvent {
|
|
263
|
+
taskId: string;
|
|
264
|
+
correlationId?: string;
|
|
265
|
+
stage: "query" | "validate" | "layout" | "encode";
|
|
266
|
+
status: "started" | "completed" | "failed";
|
|
267
|
+
reportId?: string;
|
|
268
|
+
completed?: number;
|
|
269
|
+
total?: number;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
declare interface ReportTaskMonitoring {
|
|
273
|
+
taskId?: string;
|
|
274
|
+
correlationId?: string;
|
|
275
|
+
onEvent?: ReportTaskObserver;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
declare type ReportTaskObserver = (event: ReportTaskEvent) => void;
|
|
279
|
+
|
|
259
280
|
export declare class ReportWorkerError extends Error {
|
|
260
281
|
readonly code?: string;
|
|
261
282
|
readonly path?: string;
|
|
262
283
|
readonly issues?: unknown;
|
|
284
|
+
readonly diagnostics?: unknown;
|
|
263
285
|
constructor(error: SerializedReportError);
|
|
264
286
|
}
|
|
265
287
|
|
|
@@ -289,6 +311,7 @@ declare interface SerializedReportError {
|
|
|
289
311
|
code?: string;
|
|
290
312
|
path?: string;
|
|
291
313
|
issues?: unknown;
|
|
314
|
+
diagnostics?: unknown;
|
|
292
315
|
}
|
|
293
316
|
|
|
294
317
|
/** Node Worker 入口调用;主线程调用会明确报错。 */
|
package/dist/server/node.d.ts
CHANGED
|
@@ -212,12 +212,14 @@ declare interface ReportRuntime {
|
|
|
212
212
|
|
|
213
213
|
/** 可用 worker_threads/进程/RPC 实现;接收可序列化请求,signal 由桥接层映射为取消消息。 */
|
|
214
214
|
declare interface ReportRuntimeExecutor {
|
|
215
|
-
prepare(input: Omit<ReportRuntimeInput, "signal">, signal?: AbortSignal): Promise<PreparedReport>;
|
|
216
|
-
export(input: Omit<ReportRuntimeExportInput, "signal">, signal?: AbortSignal): Promise<ReportRuntimeExportResult>;
|
|
215
|
+
prepare(input: Omit<ReportRuntimeInput, "signal" | "onEvent">, signal?: AbortSignal, onEvent?: ReportTaskObserver): Promise<PreparedReport>;
|
|
216
|
+
export(input: Omit<ReportRuntimeExportInput, "signal" | "onEvent">, signal?: AbortSignal, onEvent?: ReportTaskObserver): Promise<ReportRuntimeExportResult>;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
declare interface ReportRuntimeExportInput extends ReportRuntimeInput {
|
|
220
220
|
format: "pdf" | "xlsx";
|
|
221
|
+
/** strict 在编码前拒绝已识别的输出降级;默认保留诊断并继续。 */
|
|
222
|
+
fidelity?: "warn" | "strict";
|
|
221
223
|
/** PDF 中文需宿主显式提供有授权的字体;不隐式下载字体或资源。 */
|
|
222
224
|
pdf?: {
|
|
223
225
|
customFontBytes?: Uint8Array | ArrayBuffer;
|
|
@@ -242,7 +244,7 @@ declare interface ReportRuntimeExportResult extends Omit<PreparedReport, "plan">
|
|
|
242
244
|
contentType: string;
|
|
243
245
|
}
|
|
244
246
|
|
|
245
|
-
declare interface ReportRuntimeInput {
|
|
247
|
+
declare interface ReportRuntimeInput extends ReportTaskMonitoring {
|
|
246
248
|
reportIds: string[];
|
|
247
249
|
params?: Record<string, string>;
|
|
248
250
|
signal?: AbortSignal;
|
|
@@ -256,10 +258,30 @@ declare interface ReportRuntimeStats {
|
|
|
256
258
|
outputBytes?: number;
|
|
257
259
|
}
|
|
258
260
|
|
|
261
|
+
/** 阶段事件只包含可序列化值;不表示估算百分比,也不包含业务数据。 */
|
|
262
|
+
declare interface ReportTaskEvent {
|
|
263
|
+
taskId: string;
|
|
264
|
+
correlationId?: string;
|
|
265
|
+
stage: "query" | "validate" | "layout" | "encode";
|
|
266
|
+
status: "started" | "completed" | "failed";
|
|
267
|
+
reportId?: string;
|
|
268
|
+
completed?: number;
|
|
269
|
+
total?: number;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
declare interface ReportTaskMonitoring {
|
|
273
|
+
taskId?: string;
|
|
274
|
+
correlationId?: string;
|
|
275
|
+
onEvent?: ReportTaskObserver;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
declare type ReportTaskObserver = (event: ReportTaskEvent) => void;
|
|
279
|
+
|
|
259
280
|
export declare class ReportWorkerError extends Error {
|
|
260
281
|
readonly code?: string;
|
|
261
282
|
readonly path?: string;
|
|
262
283
|
readonly issues?: unknown;
|
|
284
|
+
readonly diagnostics?: unknown;
|
|
263
285
|
constructor(error: SerializedReportError);
|
|
264
286
|
}
|
|
265
287
|
|
|
@@ -289,6 +311,7 @@ declare interface SerializedReportError {
|
|
|
289
311
|
code?: string;
|
|
290
312
|
path?: string;
|
|
291
313
|
issues?: unknown;
|
|
314
|
+
diagnostics?: unknown;
|
|
292
315
|
}
|
|
293
316
|
|
|
294
317
|
/** Node Worker 入口调用;主线程调用会明确报错。 */
|
package/dist/server-node.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("node:worker_threads");function N(e,t,r){e.editable!==void 0&&typeof e.editable!="boolean"&&r.push({path:`${t}.editable`,message:"编辑控制应为布尔值"}),e.valueType!==void 0&&!["text","number","boolean"].includes(e.valueType)&&r.push({path:`${t}.valueType`,message:"编辑类型应为 text、number 或 boolean"})}function W(e,t,r){N(e,t,r),M(e.source,`${t}.source`,r,!0),e.formula!==void 0&&typeof e.formula!="string"&&r.push({path:`${t}.formula`,message:"单元格公式应为字符串"})}function M(e,t,r,o=!1){if(e===void 0)return;if(!e||typeof e!="object"||Array.isArray(e)){r.push({path:t,message:"业务来源应为对象"});return}const s=e;for(const n of["datasetId",...o?["field"]:[]])(typeof s[n]!="string"||!s[n].trim())&&r.push({path:`${t}.${n}`,message:"业务标识应为非空字符串"});for(const n of["rowKey","revision"]){const i=s[n];i===void 0&&!(o&&n==="rowKey")||typeof i!="string"&&!(typeof i=="number"&&Number.isFinite(i))&&r.push({path:`${t}.${n}`,message:"业务键及修订号应为字符串或有限数字"})}s.sourceToken!==void 0&&typeof s.sourceToken!="string"&&r.push({path:`${t}.sourceToken`,message:"来源令牌应为字符串"})}const T=new Set(["text","image","barcode","qrcode","chart","line","rect","ellipse"]);function p(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function O(e,t,r,o){const s=e[t];(typeof s!="number"||!Number.isFinite(s))&&o.push({path:`${r}.${t}`,message:`应为有限数字,实际 ${JSON.stringify(s)}`})}function P(e,t,r){if(e!==void 0){const o=`${t}.table`;if(!p(e))r.push({path:o,message:"逻辑表来源应为对象"});else{M(e.source,`${o}.source`,r),(typeof e.id!="string"||!e.id.trim())&&r.push({path:`${o}.id`,message:"逻辑表 ID 应为非空字符串"});const s=e.role;["header","body","group-header","subtotal","grand-total"].includes(s)||r.push({path:`${o}.role`,message:"未知逻辑表行角色"});const n=e.rowIndex;(typeof n!="number"||!Number.isInteger(n)||(s==="header"?n!==-1:n<0))&&r.push({path:`${o}.rowIndex`,message:"表头索引应为 -1,内容行索引应为非负整数"}),(!Array.isArray(e.columnKeys)||e.columnKeys.some(i=>typeof i!="string"))&&r.push({path:`${o}.columnKeys`,message:"逻辑列字段应为字符串数组"}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${o}.layout`,message:"布局应为 page 或 wide"}),e.title!==void 0&&typeof e.title!="string"&&r.push({path:`${o}.title`,message:"逻辑表名称应为字符串"})}}}function S(e,t,r,o){if(e!==void 0)if(!p(e)||!Array.isArray(e.cells))r.push({path:`${t}.grid.cells`,message:"grid.cells 应为二维数组"});else{const s=e.paddingMm;s!==void 0&&(typeof s!="number"||!Number.isFinite(s)||s<0)&&r.push({path:`${t}.grid.paddingMm`,message:"单元格内距应为有限非负数"}),e.cells.forEach((n,i)=>{if(!Array.isArray(n)){r.push({path:`${t}.grid.cells.${i}`,message:"行应为数组"});return}n.forEach((u,c)=>{if(u==null)return;const m=`${t}.grid.cells.${i}.${c}`;if(!p(u)){r.push({path:m,message:"网格单元格应为对象或 null"});return}W(u,m,r),Array.isArray(u.children)&&u.children.forEach((l,g)=>{R(l,`${t}.grid.cells.${i}.${c}.children.${g}`,r,o)})})})}}function j(e,t,r){e!==void 0&&(Array.isArray(e)?e.forEach((o,s)=>{(!p(o)||!Array.isArray(o.segments))&&r.push({path:`${t}.richParagraphs.${s}`,message:"段落缺少 segments 数组"})}):r.push({path:`${t}.richParagraphs`,message:"richParagraphs 应为数组"}))}function R(e,t,r,o=[]){if(!p(e)){r.push({path:t,message:"组件应为对象"});return}const s=e.kind;typeof s!="string"?r.push({path:`${t}.kind`,message:"组件缺少 kind 字符串"}):T.has(s)||o.push({path:`${t}.kind`,message:`未知组件类型 ${JSON.stringify(s)},将以兜底方式渲染`});for(const n of["leftMm","topMm","widthMm","heightMm"])O(e,n,t,r);typeof e.leftMm=="number"&&e.leftMm<-100&&r.push({path:`${t}.leftMm`,message:"几何数值异常(leftMm<-100)"});for(const n of["widthMm","heightMm"])typeof e[n]=="number"&&e[n]<0&&r.push({path:`${t}.${n}`,message:"组件尺寸不能为负数"});P(e.table,t,r),e.lineDirection!==void 0&&!["down","up"].includes(e.lineDirection)&&r.push({path:`${t}.lineDirection`,message:"线段方向应为 down 或 up"}),S(e.grid,t,r,o),j(e.richParagraphs,t,r)}function I(e,t,r,o=[]){if(!p(e)){r.push({path:t,message:"页应为对象"});return}const s=e.pageWidthMm,n=e.pageHeightMm;(typeof s!="number"||!Number.isFinite(s)||s<=0)&&r.push({path:`${t}.pageWidthMm`,message:`页宽非法: ${JSON.stringify(s)}`}),(typeof n!="number"||!(n>0&&n<5e3))&&r.push({path:`${t}.pageHeightMm`,message:`页高非法: ${JSON.stringify(n)}`}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${t}.layout`,message:"布局应为 page 或 wide"});const i=e.components;Array.isArray(i)?Array.isArray(i)&&i.forEach((u,c)=>R(u,`${t}.components.${c}`,r,o)):r.push({path:`${t}.components`,message:"components 应为数组"})}function K(e){const t=[],r=[],o=p(e)?e.pages:void 0;if(!Array.isArray(o))t.push({path:"$.pages",message:e==null?"渲染计划为空":"渲染计划缺少 pages 数组"});else{o.forEach((n,i)=>I(n,`$.pages.${i}`,t,r)),o.length>2e3&&r.push({path:"$.pages",message:`页数异常大(${o.length} 页),渲染与打印耗时可能显著增加`});const s=o.reduce((n,i)=>n+(p(i)&&Array.isArray(i.components)?i.components.length:0),0);s>5e4&&r.push({path:"$.pages",message:`组件总数异常大(${s} 个),可能触发浏览器性能限制`})}return{ok:t.length===0,errors:t,warnings:r}}const h="mach-report-worker/1";class k extends Error{constructor(t){super(t.message),this.name=t.name,this.code=t.code,this.path=t.path,this.issues=t.issues}}function y(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function D(e){return y(e)?["rows","pages","cells"].every(t=>typeof e[t]=="number"&&Number.isSafeInteger(e[t])&&e[t]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function F(e){return Array.isArray(e)&&e.every(t=>y(t)&&typeof t.code=="string"&&typeof t.message=="string"&&["info","warning","error"].includes(t.severity))}function _(e){return y(e)&&Object.values(e).every(t=>y(t)&&(t.revision===void 0||typeof t.revision=="string")&&(t.sourceToken===void 0||typeof t.sourceToken=="string"))}function C(e,t){if(!y(e)||!D(e.stats)||!F(e.diagnostics)||!_(e.revisions))return!1;if(t==="prepare")return K(e.plan).ok;const r=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===r}function J(e){if(!e||typeof e!="object")return{message:String(e)};const t={};for(const r of["code","path","field","message"]){const o=e[r];typeof o=="string"&&(t[r]=o)}return t}function L(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const t=e;return{name:e.name,message:e.message,...typeof t.code=="string"?{code:t.code}:{},...typeof t.path=="string"?{path:t.path}:{},...Array.isArray(t.issues)?{issues:t.issues.map(J)}:{}}}function U(e){if(!e||typeof e!="object")return!1;const t=e;return t.protocol===h&&typeof t.id=="string"&&(t.operation==="prepare"||t.operation==="export")&&!!t.input&&typeof t.input=="object"}async function q(e,t){try{const r=t.operation==="prepare"?await e.prepare(t.input):await e.export(t.input);return{protocol:h,id:t.id,result:r}}catch(r){return{protocol:h,id:t.id,error:L(r)}}}function z(e){const t=e.result;return!t||!("bytes"in t)||!(t.bytes.buffer instanceof ArrayBuffer)?[]:[t.bytes.buffer]}let B=0;function A(e){const t=new Error("报表 Worker 任务已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e}),t}function G(e,t){if(!e||typeof e!="object")return;const r=e;return r.protocol===h&&r.id===t?r:void 0}function H(e,t={}){const r=t.timeoutMs??12e4;if(!Number.isFinite(r)||r<=0||r>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(s,n,i)=>i?.aborted?Promise.reject(A(i.reason)):new Promise((u,c)=>{let m;try{m=e()}catch(a){c(a);return}const l=`mach-report-${Date.now()}-${++B}`;let g=!1,$=()=>{},b;const d=(a,f)=>{g||(g=!0,b&&clearTimeout(b),$(),i?.removeEventListener("abort",w),Promise.resolve().then(()=>m.terminate()).then(()=>a===void 0?u(f):c(a),x=>c(a??x)))},w=()=>d(A(i?.reason)),v=a=>{const f=G(a,l);f&&(f.error&&typeof f.error.name=="string"&&typeof f.error.message=="string"?d(new k(f.error)):C(f.result,s)&&(s!=="export"||"format"in f.result&&"format"in n&&f.result.format===n.format)?d(void 0,f.result):d(new Error("报表 Worker 返回无效响应")))};try{if($=m.subscribe(v,a=>d(a??new Error("报表 Worker 执行失败"))),g){$();return}i?.addEventListener("abort",w,{once:!0}),b=setTimeout(()=>d(new k({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${r}ms`})),r),i?.aborted?w():m.postMessage({protocol:h,id:l,operation:s,input:n})}catch(a){d(a)}});return{prepare:(s,n)=>o("prepare",s,n),export:(s,n)=>o("export",s,n)}}function Q(e){const t=e.filename??e.workerUrl;if(!t||e.filename&&e.workerUrl)throw new TypeError("请且仅请指定 filename 或 workerUrl");return H(()=>{const r=new E.Worker(t,e.workerOptions);return{postMessage:o=>r.postMessage(o),terminate:()=>r.terminate(),subscribe:(o,s)=>{const n=i=>s(new Error(`报表 Worker 在响应前退出(code ${i})`));return r.on("message",o),r.on("error",s),r.on("messageerror",s),r.on("exit",n),()=>{r.off("message",o),r.off("error",s),r.off("messageerror",s),r.off("exit",n)}}}},e)}function V(e){const t=E.parentPort;if(!t)throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");const r=o=>{U(o)&&q(e,o).then(s=>t.postMessage(s,z(s)))};return t.on("message",r),()=>t.off("message",r)}exports.ReportWorkerError=k;exports.createNodeReportExecutor=Q;exports.serveNodeReportWorker=V;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("node:worker_threads");function P(e,t,r){if(!r?.aborted)try{const o=e?.({...t});o&&typeof o.then=="function"&&Promise.resolve(o).catch(()=>{})}catch{}}function T(e,t,r){e.editable!==void 0&&typeof e.editable!="boolean"&&r.push({path:`${t}.editable`,message:"编辑控制应为布尔值"}),e.valueType!==void 0&&!["text","number","boolean"].includes(e.valueType)&&r.push({path:`${t}.valueType`,message:"编辑类型应为 text、number 或 boolean"})}function v(e,t,r){T(e,t,r),x(e.source,`${t}.source`,r,!0),e.formula!==void 0&&typeof e.formula!="string"&&r.push({path:`${t}.formula`,message:"单元格公式应为字符串"})}function x(e,t,r,o=!1){if(e===void 0)return;if(!e||typeof e!="object"||Array.isArray(e)){r.push({path:t,message:"业务来源应为对象"});return}const s=e;for(const n of["datasetId",...o?["field"]:[]])(typeof s[n]!="string"||!s[n].trim())&&r.push({path:`${t}.${n}`,message:"业务标识应为非空字符串"});for(const n of["rowKey","revision"]){const i=s[n];i===void 0&&!(o&&n==="rowKey")||typeof i!="string"&&!(typeof i=="number"&&Number.isFinite(i))&&r.push({path:`${t}.${n}`,message:"业务键及修订号应为字符串或有限数字"})}s.sourceToken!==void 0&&typeof s.sourceToken!="string"&&r.push({path:`${t}.sourceToken`,message:"来源令牌应为字符串"})}const O=new Set(["text","image","barcode","qrcode","chart","line","rect","ellipse"]);function d(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function S(e,t,r,o){const s=e[t];(typeof s!="number"||!Number.isFinite(s))&&o.push({path:`${r}.${t}`,message:`应为有限数字,实际 ${JSON.stringify(s)}`})}function j(e,t,r){if(e!==void 0){const o=`${t}.table`;if(!d(e))r.push({path:o,message:"逻辑表来源应为对象"});else{x(e.source,`${o}.source`,r),(typeof e.id!="string"||!e.id.trim())&&r.push({path:`${o}.id`,message:"逻辑表 ID 应为非空字符串"});const s=e.role;["header","body","group-header","subtotal","grand-total"].includes(s)||r.push({path:`${o}.role`,message:"未知逻辑表行角色"});const n=e.rowIndex;(typeof n!="number"||!Number.isInteger(n)||(s==="header"?n!==-1:n<0))&&r.push({path:`${o}.rowIndex`,message:"表头索引应为 -1,内容行索引应为非负整数"}),(!Array.isArray(e.columnKeys)||e.columnKeys.some(i=>typeof i!="string"))&&r.push({path:`${o}.columnKeys`,message:"逻辑列字段应为字符串数组"}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${o}.layout`,message:"布局应为 page 或 wide"}),e.title!==void 0&&typeof e.title!="string"&&r.push({path:`${o}.title`,message:"逻辑表名称应为字符串"})}}}function K(e,t,r,o){if(e!==void 0)if(!d(e)||!Array.isArray(e.cells))r.push({path:`${t}.grid.cells`,message:"grid.cells 应为二维数组"});else{const s=e.paddingMm;s!==void 0&&(typeof s!="number"||!Number.isFinite(s)||s<0)&&r.push({path:`${t}.grid.paddingMm`,message:"单元格内距应为有限非负数"}),e.cells.forEach((n,i)=>{if(!Array.isArray(n)){r.push({path:`${t}.grid.cells.${i}`,message:"行应为数组"});return}n.forEach((c,m)=>{if(c==null)return;const g=`${t}.grid.cells.${i}.${m}`;if(!d(c)){r.push({path:g,message:"网格单元格应为对象或 null"});return}v(c,g,r),Array.isArray(c.children)&&c.children.forEach((y,b)=>{I(y,`${t}.grid.cells.${i}.${m}.children.${b}`,r,o)})})})}}function _(e,t,r){e!==void 0&&(Array.isArray(e)?e.forEach((o,s)=>{(!d(o)||!Array.isArray(o.segments))&&r.push({path:`${t}.richParagraphs.${s}`,message:"段落缺少 segments 数组"})}):r.push({path:`${t}.richParagraphs`,message:"richParagraphs 应为数组"}))}function I(e,t,r,o=[]){if(!d(e)){r.push({path:t,message:"组件应为对象"});return}const s=e.kind;typeof s!="string"?r.push({path:`${t}.kind`,message:"组件缺少 kind 字符串"}):O.has(s)||o.push({path:`${t}.kind`,message:`未知组件类型 ${JSON.stringify(s)},将以兜底方式渲染`});for(const n of["leftMm","topMm","widthMm","heightMm"])S(e,n,t,r);typeof e.leftMm=="number"&&e.leftMm<-100&&r.push({path:`${t}.leftMm`,message:"几何数值异常(leftMm<-100)"});for(const n of["widthMm","heightMm"])typeof e[n]=="number"&&e[n]<0&&r.push({path:`${t}.${n}`,message:"组件尺寸不能为负数"});j(e.table,t,r),e.lineDirection!==void 0&&!["down","up"].includes(e.lineDirection)&&r.push({path:`${t}.lineDirection`,message:"线段方向应为 down 或 up"}),K(e.grid,t,r,o),_(e.richParagraphs,t,r)}function D(e,t,r,o=[]){if(!d(e)){r.push({path:t,message:"页应为对象"});return}const s=e.pageWidthMm,n=e.pageHeightMm;(typeof s!="number"||!Number.isFinite(s)||s<=0)&&r.push({path:`${t}.pageWidthMm`,message:`页宽非法: ${JSON.stringify(s)}`}),(typeof n!="number"||!(n>0&&n<5e3))&&r.push({path:`${t}.pageHeightMm`,message:`页高非法: ${JSON.stringify(n)}`}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${t}.layout`,message:"布局应为 page 或 wide"});const i=e.components;Array.isArray(i)?Array.isArray(i)&&i.forEach((c,m)=>I(c,`${t}.components.${m}`,r,o)):r.push({path:`${t}.components`,message:"components 应为数组"})}function F(e){const t=[],r=[],o=d(e)?e.pages:void 0;if(!Array.isArray(o))t.push({path:"$.pages",message:e==null?"渲染计划为空":"渲染计划缺少 pages 数组"});else{o.forEach((n,i)=>D(n,`$.pages.${i}`,t,r)),o.length>2e3&&r.push({path:"$.pages",message:`页数异常大(${o.length} 页),渲染与打印耗时可能显著增加`});const s=o.reduce((n,i)=>n+(d(i)&&Array.isArray(i.components)?i.components.length:0),0);s>5e4&&r.push({path:"$.pages",message:`组件总数异常大(${s} 个),可能触发浏览器性能限制`})}return{ok:t.length===0,errors:t,warnings:r}}const l="mach-report-worker/1";class E extends Error{constructor(t){super(t.message),this.name=t.name,this.code=t.code,this.path=t.path,this.issues=t.issues,this.diagnostics=t.diagnostics}}function u(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function z(e){return u(e)?["rows","pages","cells"].every(t=>typeof e[t]=="number"&&Number.isSafeInteger(e[t])&&e[t]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function C(e){return Array.isArray(e)&&e.every(t=>u(t)&&typeof t.code=="string"&&typeof t.message=="string"&&["info","warning","error"].includes(t.severity))}function J(e){return u(e)&&Object.values(e).every(t=>u(t)&&(t.revision===void 0||typeof t.revision=="string")&&(t.sourceToken===void 0||typeof t.sourceToken=="string"))}function L(e,t){if(!u(e)||!z(e.stats)||!C(e.diagnostics)||!J(e.revisions))return!1;if(t==="prepare")return F(e.plan).ok;const r=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===r}function N(e){if(!e||typeof e!="object")return{message:String(e)};const t={};for(const r of["code","path","field","message"]){const o=e[r];typeof o=="string"&&(t[r]=o)}return t}function U(e){const t=N(e);if(!u(e))return t;for(const r of["format","severity","kind","nid"])typeof e[r]=="string"&&(t[r]=e[r]);for(const r of["pageIndex","componentIndex"])Number.isSafeInteger(e[r])&&e[r]>=0&&(t[r]=e[r]);return Array.isArray(e.componentPath)&&e.componentPath.every(r=>Number.isSafeInteger(r)&&r>=0)&&(t.componentPath=e.componentPath),t}function q(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const t=e;return{name:e.name,message:e.message,...typeof t.code=="string"?{code:t.code}:{},...typeof t.path=="string"?{path:t.path}:{},...Array.isArray(t.issues)?{issues:t.issues.map(N)}:{},...Array.isArray(t.diagnostics)?{diagnostics:t.diagnostics.map(U)}:{}}}function B(e){if(!e||typeof e!="object")return!1;const t=e;return t.protocol===l&&typeof t.id=="string"&&(t.operation==="prepare"||t.operation==="export")&&!!t.input&&typeof t.input=="object"}async function G(e,t,r){try{const o=t.operation==="prepare"?await e.prepare({...t.input,onEvent:r}):await e.export({...t.input,onEvent:r});return{protocol:l,id:t.id,result:o}}catch(o){return{protocol:l,id:t.id,error:q(o)}}}function H(e){const t=e.result;return!t||!("bytes"in t)||!(t.bytes.buffer instanceof ArrayBuffer)?[]:[t.bytes.buffer]}function Q(e,t){if(!u(e)||typeof e.taskId!="string"||!e.taskId||t.taskId!==void 0&&e.taskId!==t.taskId||e.correlationId!==t.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!t.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const r of["completed","total"])if(e[r]!==void 0&&(typeof e[r]!="number"||!Number.isFinite(e[r])||e[r]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let V=0;function M(e){const t=new Error("报表 Worker 任务已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e}),t}function X(e,t){if(!e||typeof e!="object")return;const r=e;return r.protocol===l&&r.id===t?r:void 0}function Y(e,t={}){const r=t.timeoutMs??12e4;if(!Number.isFinite(r)||r<=0||r>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(s,n,i,c)=>i?.aborted?Promise.reject(M(i.reason)):new Promise((m,g)=>{let y;try{y=e()}catch(f){g(f);return}const b=`mach-report-${Date.now()}-${++V}`;let $=!1,k=()=>{},w;const p=(f,a)=>{$||($=!0,w&&clearTimeout(w),k(),i?.removeEventListener("abort",A),Promise.resolve().then(()=>y.terminate()).then(()=>f===void 0?m(a):g(f),h=>g(f??h)))},A=()=>p(M(i?.reason)),W=f=>{const a=X(f,b);if(!(!a||$)){if("type"in a&&a.type==="event"){const h="event"in a?a.event:void 0;Q(h,n)?P(c,h,i):p(new Error("报表 Worker 返回无效阶段事件"));return}a.error&&typeof a.error.name=="string"&&typeof a.error.message=="string"?p(new E(a.error)):L(a.result,s)&&(s!=="export"||"format"in a.result&&"format"in n&&a.result.format===n.format)?p(void 0,a.result):p(new Error("报表 Worker 返回无效响应"))}};try{if(k=y.subscribe(W,f=>p(f??new Error("报表 Worker 执行失败"))),$){k();return}if(i?.addEventListener("abort",A,{once:!0}),w=setTimeout(()=>p(new E({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${r}ms`})),r),i?.aborted)A();else{const{onEvent:f,signal:a,...h}=n;y.postMessage({protocol:l,id:b,operation:s,input:h})}}catch(f){p(f)}});return{prepare:(s,n,i)=>o("prepare",s,n,i),export:(s,n,i)=>o("export",s,n,i)}}function Z(e){const t=e.filename??e.workerUrl;if(!t||e.filename&&e.workerUrl)throw new TypeError("请且仅请指定 filename 或 workerUrl");return Y(()=>{const r=new R.Worker(t,e.workerOptions);return{postMessage:o=>r.postMessage(o),terminate:()=>r.terminate(),subscribe:(o,s)=>{const n=i=>s(new Error(`报表 Worker 在响应前退出(code ${i})`));return r.on("message",o),r.on("error",s),r.on("messageerror",s),r.on("exit",n),()=>{r.off("message",o),r.off("error",s),r.off("messageerror",s),r.off("exit",n)}}}},e)}function ee(e){const t=R.parentPort;if(!t)throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");const r=o=>{B(o)&&G(e,o,s=>t.postMessage({protocol:l,id:o.id,type:"event",event:s})).then(s=>t.postMessage(s,H(s)))};return t.on("message",r),()=>t.off("message",r)}exports.ReportWorkerError=E;exports.createNodeReportExecutor=Z;exports.serveNodeReportWorker=ee;
|
package/dist/server-node.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import { parentPort as
|
|
2
|
-
function
|
|
1
|
+
import { parentPort as W, Worker as P } from "node:worker_threads";
|
|
2
|
+
function T(e, t, r) {
|
|
3
|
+
if (!r?.aborted)
|
|
4
|
+
try {
|
|
5
|
+
const o = e?.({ ...t });
|
|
6
|
+
o && typeof o.then == "function" && Promise.resolve(o).catch(() => {
|
|
7
|
+
});
|
|
8
|
+
} catch {
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function v(e, t, r) {
|
|
3
12
|
e.editable !== void 0 && typeof e.editable != "boolean" && r.push({ path: `${t}.editable`, message: "编辑控制应为布尔值" }), e.valueType !== void 0 && !["text", "number", "boolean"].includes(e.valueType) && r.push({ path: `${t}.valueType`, message: "编辑类型应为 text、number 或 boolean" });
|
|
4
13
|
}
|
|
5
|
-
function
|
|
6
|
-
|
|
14
|
+
function O(e, t, r) {
|
|
15
|
+
v(e, t, r), x(e.source, `${t}.source`, r, !0), e.formula !== void 0 && typeof e.formula != "string" && r.push({ path: `${t}.formula`, message: "单元格公式应为字符串" });
|
|
7
16
|
}
|
|
8
|
-
function
|
|
17
|
+
function x(e, t, r, o = !1) {
|
|
9
18
|
if (e === void 0) return;
|
|
10
19
|
if (!e || typeof e != "object" || Array.isArray(e)) {
|
|
11
20
|
r.push({ path: t, message: "业务来源应为对象" });
|
|
@@ -20,7 +29,7 @@ function E(e, t, r, o = !1) {
|
|
|
20
29
|
}
|
|
21
30
|
s.sourceToken !== void 0 && typeof s.sourceToken != "string" && r.push({ path: `${t}.sourceToken`, message: "来源令牌应为字符串" });
|
|
22
31
|
}
|
|
23
|
-
const
|
|
32
|
+
const S = /* @__PURE__ */ new Set([
|
|
24
33
|
"text",
|
|
25
34
|
"image",
|
|
26
35
|
"barcode",
|
|
@@ -30,19 +39,19 @@ const O = /* @__PURE__ */ new Set([
|
|
|
30
39
|
"rect",
|
|
31
40
|
"ellipse"
|
|
32
41
|
]);
|
|
33
|
-
function
|
|
42
|
+
function d(e) {
|
|
34
43
|
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
35
44
|
}
|
|
36
|
-
function
|
|
45
|
+
function j(e, t, r, o) {
|
|
37
46
|
const s = e[t];
|
|
38
47
|
(typeof s != "number" || !Number.isFinite(s)) && o.push({ path: `${r}.${t}`, message: `应为有限数字,实际 ${JSON.stringify(s)}` });
|
|
39
48
|
}
|
|
40
|
-
function
|
|
49
|
+
function K(e, t, r) {
|
|
41
50
|
if (e !== void 0) {
|
|
42
51
|
const o = `${t}.table`;
|
|
43
|
-
if (!
|
|
52
|
+
if (!d(e)) r.push({ path: o, message: "逻辑表来源应为对象" });
|
|
44
53
|
else {
|
|
45
|
-
|
|
54
|
+
x(e.source, `${o}.source`, r), (typeof e.id != "string" || !e.id.trim()) && r.push({ path: `${o}.id`, message: "逻辑表 ID 应为非空字符串" });
|
|
46
55
|
const s = e.role;
|
|
47
56
|
["header", "body", "group-header", "subtotal", "grand-total"].includes(s) || r.push({ path: `${o}.role`, message: "未知逻辑表行角色" });
|
|
48
57
|
const n = e.rowIndex;
|
|
@@ -50,9 +59,9 @@ function S(e, t, r) {
|
|
|
50
59
|
}
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
|
-
function
|
|
62
|
+
function D(e, t, r, o) {
|
|
54
63
|
if (e !== void 0)
|
|
55
|
-
if (!
|
|
64
|
+
if (!d(e) || !Array.isArray(e.cells))
|
|
56
65
|
r.push({ path: `${t}.grid.cells`, message: "grid.cells 应为二维数组" });
|
|
57
66
|
else {
|
|
58
67
|
const s = e.paddingMm;
|
|
@@ -61,44 +70,44 @@ function j(e, t, r, o) {
|
|
|
61
70
|
r.push({ path: `${t}.grid.cells.${i}`, message: "行应为数组" });
|
|
62
71
|
return;
|
|
63
72
|
}
|
|
64
|
-
n.forEach((
|
|
65
|
-
if (
|
|
66
|
-
const
|
|
67
|
-
if (!
|
|
68
|
-
r.push({ path:
|
|
73
|
+
n.forEach((c, m) => {
|
|
74
|
+
if (c == null) return;
|
|
75
|
+
const g = `${t}.grid.cells.${i}.${m}`;
|
|
76
|
+
if (!d(c)) {
|
|
77
|
+
r.push({ path: g, message: "网格单元格应为对象或 null" });
|
|
69
78
|
return;
|
|
70
79
|
}
|
|
71
|
-
|
|
72
|
-
|
|
80
|
+
O(c, g, r), Array.isArray(c.children) && c.children.forEach((y, $) => {
|
|
81
|
+
I(y, `${t}.grid.cells.${i}.${m}.children.${$}`, r, o);
|
|
73
82
|
});
|
|
74
83
|
});
|
|
75
84
|
});
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
|
-
function
|
|
87
|
+
function F(e, t, r) {
|
|
79
88
|
e !== void 0 && (Array.isArray(e) ? e.forEach((o, s) => {
|
|
80
|
-
(!
|
|
89
|
+
(!d(o) || !Array.isArray(o.segments)) && r.push({ path: `${t}.richParagraphs.${s}`, message: "段落缺少 segments 数组" });
|
|
81
90
|
}) : r.push({ path: `${t}.richParagraphs`, message: "richParagraphs 应为数组" }));
|
|
82
91
|
}
|
|
83
|
-
function
|
|
84
|
-
if (!
|
|
92
|
+
function I(e, t, r, o = []) {
|
|
93
|
+
if (!d(e)) {
|
|
85
94
|
r.push({ path: t, message: "组件应为对象" });
|
|
86
95
|
return;
|
|
87
96
|
}
|
|
88
97
|
const s = e.kind;
|
|
89
|
-
typeof s != "string" ? r.push({ path: `${t}.kind`, message: "组件缺少 kind 字符串" }) :
|
|
98
|
+
typeof s != "string" ? r.push({ path: `${t}.kind`, message: "组件缺少 kind 字符串" }) : S.has(s) || o.push({
|
|
90
99
|
path: `${t}.kind`,
|
|
91
100
|
message: `未知组件类型 ${JSON.stringify(s)},将以兜底方式渲染`
|
|
92
101
|
});
|
|
93
102
|
for (const n of ["leftMm", "topMm", "widthMm", "heightMm"])
|
|
94
|
-
|
|
103
|
+
j(e, n, t, r);
|
|
95
104
|
typeof e.leftMm == "number" && e.leftMm < -100 && r.push({ path: `${t}.leftMm`, message: "几何数值异常(leftMm<-100)" });
|
|
96
105
|
for (const n of ["widthMm", "heightMm"])
|
|
97
106
|
typeof e[n] == "number" && e[n] < 0 && r.push({ path: `${t}.${n}`, message: "组件尺寸不能为负数" });
|
|
98
|
-
|
|
107
|
+
K(e.table, t, r), e.lineDirection !== void 0 && !["down", "up"].includes(e.lineDirection) && r.push({ path: `${t}.lineDirection`, message: "线段方向应为 down 或 up" }), D(e.grid, t, r, o), F(e.richParagraphs, t, r);
|
|
99
108
|
}
|
|
100
|
-
function
|
|
101
|
-
if (!
|
|
109
|
+
function _(e, t, r, o = []) {
|
|
110
|
+
if (!d(e)) {
|
|
102
111
|
r.push({ path: t, message: "页应为对象" });
|
|
103
112
|
return;
|
|
104
113
|
}
|
|
@@ -106,23 +115,23 @@ function K(e, t, r, o = []) {
|
|
|
106
115
|
(typeof s != "number" || !Number.isFinite(s) || s <= 0) && r.push({ path: `${t}.pageWidthMm`, message: `页宽非法: ${JSON.stringify(s)}` }), (typeof n != "number" || !(n > 0 && n < 5e3)) && r.push({ path: `${t}.pageHeightMm`, message: `页高非法: ${JSON.stringify(n)}` }), e.layout !== void 0 && e.layout !== "page" && e.layout !== "wide" && r.push({ path: `${t}.layout`, message: "布局应为 page 或 wide" });
|
|
107
116
|
const i = e.components;
|
|
108
117
|
Array.isArray(i) ? Array.isArray(i) && i.forEach(
|
|
109
|
-
(
|
|
118
|
+
(c, m) => I(c, `${t}.components.${m}`, r, o)
|
|
110
119
|
) : r.push({ path: `${t}.components`, message: "components 应为数组" });
|
|
111
120
|
}
|
|
112
|
-
function
|
|
113
|
-
const t = [], r = [], o =
|
|
121
|
+
function z(e) {
|
|
122
|
+
const t = [], r = [], o = d(e) ? e.pages : void 0;
|
|
114
123
|
if (!Array.isArray(o))
|
|
115
124
|
t.push({
|
|
116
125
|
path: "$.pages",
|
|
117
126
|
message: e == null ? "渲染计划为空" : "渲染计划缺少 pages 数组"
|
|
118
127
|
});
|
|
119
128
|
else {
|
|
120
|
-
o.forEach((n, i) =>
|
|
129
|
+
o.forEach((n, i) => _(n, `$.pages.${i}`, t, r)), o.length > 2e3 && r.push({
|
|
121
130
|
path: "$.pages",
|
|
122
131
|
message: `页数异常大(${o.length} 页),渲染与打印耗时可能显著增加`
|
|
123
132
|
});
|
|
124
133
|
const s = o.reduce(
|
|
125
|
-
(n, i) => n + (
|
|
134
|
+
(n, i) => n + (d(i) && Array.isArray(i.components) ? i.components.length : 0),
|
|
126
135
|
0
|
|
127
136
|
);
|
|
128
137
|
s > 5e4 && r.push({
|
|
@@ -132,31 +141,31 @@ function D(e) {
|
|
|
132
141
|
}
|
|
133
142
|
return { ok: t.length === 0, errors: t, warnings: r };
|
|
134
143
|
}
|
|
135
|
-
const
|
|
136
|
-
class
|
|
144
|
+
const l = "mach-report-worker/1";
|
|
145
|
+
class E extends Error {
|
|
137
146
|
constructor(t) {
|
|
138
|
-
super(t.message), this.name = t.name, this.code = t.code, this.path = t.path, this.issues = t.issues;
|
|
147
|
+
super(t.message), this.name = t.name, this.code = t.code, this.path = t.path, this.issues = t.issues, this.diagnostics = t.diagnostics;
|
|
139
148
|
}
|
|
140
149
|
}
|
|
141
|
-
function
|
|
150
|
+
function u(e) {
|
|
142
151
|
return !!e && typeof e == "object" && !Array.isArray(e);
|
|
143
152
|
}
|
|
144
|
-
function F(e) {
|
|
145
|
-
return y(e) ? ["rows", "pages", "cells"].every((t) => typeof e[t] == "number" && Number.isSafeInteger(e[t]) && e[t] >= 0) && typeof e.durationMs == "number" && Number.isFinite(e.durationMs) && e.durationMs >= 0 : !1;
|
|
146
|
-
}
|
|
147
153
|
function C(e) {
|
|
148
|
-
return
|
|
154
|
+
return u(e) ? ["rows", "pages", "cells"].every((t) => typeof e[t] == "number" && Number.isSafeInteger(e[t]) && e[t] >= 0) && typeof e.durationMs == "number" && Number.isFinite(e.durationMs) && e.durationMs >= 0 : !1;
|
|
149
155
|
}
|
|
150
156
|
function J(e) {
|
|
151
|
-
return
|
|
157
|
+
return Array.isArray(e) && e.every((t) => u(t) && typeof t.code == "string" && typeof t.message == "string" && ["info", "warning", "error"].includes(t.severity));
|
|
152
158
|
}
|
|
153
|
-
function L(e
|
|
154
|
-
|
|
155
|
-
|
|
159
|
+
function L(e) {
|
|
160
|
+
return u(e) && Object.values(e).every((t) => u(t) && (t.revision === void 0 || typeof t.revision == "string") && (t.sourceToken === void 0 || typeof t.sourceToken == "string"));
|
|
161
|
+
}
|
|
162
|
+
function U(e, t) {
|
|
163
|
+
if (!u(e) || !C(e.stats) || !J(e.diagnostics) || !L(e.revisions)) return !1;
|
|
164
|
+
if (t === "prepare") return z(e.plan).ok;
|
|
156
165
|
const r = e.format === "pdf" ? "application/pdf" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
157
166
|
return e.bytes instanceof Uint8Array && (e.format === "pdf" || e.format === "xlsx") && e.contentType === r;
|
|
158
167
|
}
|
|
159
|
-
function
|
|
168
|
+
function R(e) {
|
|
160
169
|
if (!e || typeof e != "object") return { message: String(e) };
|
|
161
170
|
const t = {};
|
|
162
171
|
for (const r of ["code", "path", "field", "message"]) {
|
|
@@ -165,7 +174,14 @@ function U(e) {
|
|
|
165
174
|
}
|
|
166
175
|
return t;
|
|
167
176
|
}
|
|
168
|
-
function
|
|
177
|
+
function q(e) {
|
|
178
|
+
const t = R(e);
|
|
179
|
+
if (!u(e)) return t;
|
|
180
|
+
for (const r of ["format", "severity", "kind", "nid"]) typeof e[r] == "string" && (t[r] = e[r]);
|
|
181
|
+
for (const r of ["pageIndex", "componentIndex"]) Number.isSafeInteger(e[r]) && e[r] >= 0 && (t[r] = e[r]);
|
|
182
|
+
return Array.isArray(e.componentPath) && e.componentPath.every((r) => Number.isSafeInteger(r) && r >= 0) && (t.componentPath = e.componentPath), t;
|
|
183
|
+
}
|
|
184
|
+
function B(e) {
|
|
169
185
|
if (!(e instanceof Error)) return { name: "Error", message: String(e) };
|
|
170
186
|
const t = e;
|
|
171
187
|
return {
|
|
@@ -173,76 +189,93 @@ function _(e) {
|
|
|
173
189
|
message: e.message,
|
|
174
190
|
...typeof t.code == "string" ? { code: t.code } : {},
|
|
175
191
|
...typeof t.path == "string" ? { path: t.path } : {},
|
|
176
|
-
...Array.isArray(t.issues) ? { issues: t.issues.map(
|
|
192
|
+
...Array.isArray(t.issues) ? { issues: t.issues.map(R) } : {},
|
|
193
|
+
...Array.isArray(t.diagnostics) ? { diagnostics: t.diagnostics.map(q) } : {}
|
|
177
194
|
};
|
|
178
195
|
}
|
|
179
|
-
function
|
|
196
|
+
function G(e) {
|
|
180
197
|
if (!e || typeof e != "object") return !1;
|
|
181
198
|
const t = e;
|
|
182
|
-
return t.protocol ===
|
|
199
|
+
return t.protocol === l && typeof t.id == "string" && (t.operation === "prepare" || t.operation === "export") && !!t.input && typeof t.input == "object";
|
|
183
200
|
}
|
|
184
|
-
async function
|
|
201
|
+
async function H(e, t, r) {
|
|
185
202
|
try {
|
|
186
|
-
const
|
|
187
|
-
return { protocol:
|
|
188
|
-
} catch (
|
|
189
|
-
return { protocol:
|
|
203
|
+
const o = t.operation === "prepare" ? await e.prepare({ ...t.input, onEvent: r }) : await e.export({ ...t.input, onEvent: r });
|
|
204
|
+
return { protocol: l, id: t.id, result: o };
|
|
205
|
+
} catch (o) {
|
|
206
|
+
return { protocol: l, id: t.id, error: B(o) };
|
|
190
207
|
}
|
|
191
208
|
}
|
|
192
|
-
function
|
|
209
|
+
function Q(e) {
|
|
193
210
|
const t = e.result;
|
|
194
211
|
return !t || !("bytes" in t) || !(t.bytes.buffer instanceof ArrayBuffer) ? [] : [t.bytes.buffer];
|
|
195
212
|
}
|
|
196
|
-
|
|
197
|
-
|
|
213
|
+
function V(e, t) {
|
|
214
|
+
if (!u(e) || typeof e.taskId != "string" || !e.taskId || t.taskId !== void 0 && e.taskId !== t.taskId || e.correlationId !== t.correlationId || e.reportId !== void 0 && (typeof e.reportId != "string" || !t.reportIds.includes(e.reportId)) || !["query", "validate", "layout", "encode"].includes(e.stage) || !["started", "completed", "failed"].includes(e.status)) return !1;
|
|
215
|
+
for (const r of ["completed", "total"]) if (e[r] !== void 0 && (typeof e[r] != "number" || !Number.isFinite(e[r]) || e[r] < 0)) return !1;
|
|
216
|
+
return e.completed === void 0 || e.total === void 0 || e.completed <= e.total;
|
|
217
|
+
}
|
|
218
|
+
let X = 0;
|
|
219
|
+
function M(e) {
|
|
198
220
|
const t = new Error("报表 Worker 任务已取消");
|
|
199
221
|
return t.name = "AbortError", Object.defineProperty(t, "cause", { value: e }), t;
|
|
200
222
|
}
|
|
201
|
-
function
|
|
223
|
+
function Y(e, t) {
|
|
202
224
|
if (!e || typeof e != "object") return;
|
|
203
225
|
const r = e;
|
|
204
|
-
return r.protocol ===
|
|
226
|
+
return r.protocol === l && r.id === t ? r : void 0;
|
|
205
227
|
}
|
|
206
|
-
function
|
|
228
|
+
function Z(e, t = {}) {
|
|
207
229
|
const r = t.timeoutMs ?? 12e4;
|
|
208
230
|
if (!Number.isFinite(r) || r <= 0 || r > 2147483647) throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");
|
|
209
|
-
const o = (s, n, i) => i?.aborted ? Promise.reject(
|
|
210
|
-
let
|
|
231
|
+
const o = (s, n, i, c) => i?.aborted ? Promise.reject(M(i.reason)) : new Promise((m, g) => {
|
|
232
|
+
let y;
|
|
211
233
|
try {
|
|
212
|
-
|
|
213
|
-
} catch (
|
|
214
|
-
|
|
234
|
+
y = e();
|
|
235
|
+
} catch (f) {
|
|
236
|
+
g(f);
|
|
215
237
|
return;
|
|
216
238
|
}
|
|
217
|
-
const
|
|
218
|
-
let
|
|
219
|
-
},
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
() =>
|
|
223
|
-
(
|
|
239
|
+
const $ = `mach-report-${Date.now()}-${++X}`;
|
|
240
|
+
let b = !1, k = () => {
|
|
241
|
+
}, w;
|
|
242
|
+
const p = (f, a) => {
|
|
243
|
+
b || (b = !0, w && clearTimeout(w), k(), i?.removeEventListener("abort", A), Promise.resolve().then(() => y.terminate()).then(
|
|
244
|
+
() => f === void 0 ? m(a) : g(f),
|
|
245
|
+
(h) => g(f ?? h)
|
|
224
246
|
));
|
|
225
|
-
},
|
|
226
|
-
const
|
|
227
|
-
|
|
247
|
+
}, A = () => p(M(i?.reason)), N = (f) => {
|
|
248
|
+
const a = Y(f, $);
|
|
249
|
+
if (!(!a || b)) {
|
|
250
|
+
if ("type" in a && a.type === "event") {
|
|
251
|
+
const h = "event" in a ? a.event : void 0;
|
|
252
|
+
V(h, n) ? T(c, h, i) : p(new Error("报表 Worker 返回无效阶段事件"));
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
a.error && typeof a.error.name == "string" && typeof a.error.message == "string" ? p(new E(a.error)) : U(a.result, s) && (s !== "export" || "format" in a.result && "format" in n && a.result.format === n.format) ? p(void 0, a.result) : p(new Error("报表 Worker 返回无效响应"));
|
|
256
|
+
}
|
|
228
257
|
};
|
|
229
258
|
try {
|
|
230
|
-
if (
|
|
231
|
-
|
|
259
|
+
if (k = y.subscribe(N, (f) => p(f ?? new Error("报表 Worker 执行失败"))), b) {
|
|
260
|
+
k();
|
|
232
261
|
return;
|
|
233
262
|
}
|
|
234
|
-
i?.addEventListener("abort",
|
|
235
|
-
|
|
236
|
-
|
|
263
|
+
if (i?.addEventListener("abort", A, { once: !0 }), w = setTimeout(() => p(new E({ name: "ReportRuntimeError", code: "timeout", message: `报表 Worker 执行超过 ${r}ms` })), r), i?.aborted) A();
|
|
264
|
+
else {
|
|
265
|
+
const { onEvent: f, signal: a, ...h } = n;
|
|
266
|
+
y.postMessage({ protocol: l, id: $, operation: s, input: h });
|
|
267
|
+
}
|
|
268
|
+
} catch (f) {
|
|
269
|
+
p(f);
|
|
237
270
|
}
|
|
238
271
|
});
|
|
239
|
-
return { prepare: (s, n) => o("prepare", s, n), export: (s, n) => o("export", s, n) };
|
|
272
|
+
return { prepare: (s, n, i) => o("prepare", s, n, i), export: (s, n, i) => o("export", s, n, i) };
|
|
240
273
|
}
|
|
241
|
-
function
|
|
274
|
+
function te(e) {
|
|
242
275
|
const t = e.filename ?? e.workerUrl;
|
|
243
276
|
if (!t || e.filename && e.workerUrl) throw new TypeError("请且仅请指定 filename 或 workerUrl");
|
|
244
|
-
return
|
|
245
|
-
const r = new
|
|
277
|
+
return Z(() => {
|
|
278
|
+
const r = new P(t, e.workerOptions);
|
|
246
279
|
return {
|
|
247
280
|
postMessage: (o) => r.postMessage(o),
|
|
248
281
|
terminate: () => r.terminate(),
|
|
@@ -255,16 +288,16 @@ function X(e) {
|
|
|
255
288
|
};
|
|
256
289
|
}, e);
|
|
257
290
|
}
|
|
258
|
-
function
|
|
259
|
-
const t =
|
|
291
|
+
function re(e) {
|
|
292
|
+
const t = W;
|
|
260
293
|
if (!t) throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");
|
|
261
294
|
const r = (o) => {
|
|
262
|
-
|
|
295
|
+
G(o) && H(e, o, (s) => t.postMessage({ protocol: l, id: o.id, type: "event", event: s })).then((s) => t.postMessage(s, Q(s)));
|
|
263
296
|
};
|
|
264
297
|
return t.on("message", r), () => t.off("message", r);
|
|
265
298
|
}
|
|
266
299
|
export {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
300
|
+
E as ReportWorkerError,
|
|
301
|
+
te as createNodeReportExecutor,
|
|
302
|
+
re as serveNodeReportWorker
|
|
270
303
|
};
|