@veltra/desktop 1.7.13 → 1.7.15

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 (84) hide show
  1. package/dist/components/batch-edit/batch-edit-form.js +9 -3
  2. package/dist/components/batch-edit/batch-edit-form.js.map +1 -1
  3. package/dist/components/batch-edit/batch-edit-list.js +2 -1
  4. package/dist/components/batch-edit/batch-edit-list.js.map +1 -1
  5. package/dist/components/batch-edit/batch-edit.js +57 -30
  6. package/dist/components/batch-edit/batch-edit.js.map +1 -1
  7. package/dist/components/batch-edit/style.d.ts +1 -0
  8. package/dist/components/batch-edit/style.js +1 -0
  9. package/dist/components/batch-edit/style2.css +14 -0
  10. package/dist/components/batch-edit/use-dialog-effect.js +20 -0
  11. package/dist/components/batch-edit/use-dialog-effect.js.map +1 -0
  12. package/dist/components/batch-edit/use-edit-state.js +22 -3
  13. package/dist/components/batch-edit/use-edit-state.js.map +1 -1
  14. package/dist/components/batch-edit/use-handlers.js +5 -0
  15. package/dist/components/batch-edit/use-handlers.js.map +1 -1
  16. package/dist/components/batch-edit/use-shortcut-key.js +5 -2
  17. package/dist/components/batch-edit/use-shortcut-key.js.map +1 -1
  18. package/dist/components/file-viewer/file-viewer.js +21 -14
  19. package/dist/components/file-viewer/file-viewer.js.map +1 -1
  20. package/dist/components/file-viewer/helper.js +2 -0
  21. package/dist/components/file-viewer/helper.js.map +1 -1
  22. package/dist/components/file-viewer/previewers/ofd-previewer.js +196 -0
  23. package/dist/components/file-viewer/previewers/ofd-previewer.js.map +1 -0
  24. package/dist/components/file-viewer/style2.css +27 -0
  25. package/dist/components/table-editor/style2.css +23 -3
  26. package/dist/components/table-editor/table-editor.js +213 -63
  27. package/dist/components/table-editor/table-editor.js.map +1 -1
  28. package/dist/components/tip/style2.css +63 -0
  29. package/dist/components/tip/tip.js +6 -1
  30. package/dist/components/tip/tip.js.map +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/packages/ofd-core/dist/color.js +69 -0
  33. package/dist/packages/ofd-core/dist/color.js.map +1 -0
  34. package/dist/packages/ofd-core/dist/ctm.js +55 -0
  35. package/dist/packages/ofd-core/dist/ctm.js.map +1 -0
  36. package/dist/packages/ofd-core/dist/error.js +14 -0
  37. package/dist/packages/ofd-core/dist/error.js.map +1 -0
  38. package/dist/packages/ofd-core/dist/font.js +384 -0
  39. package/dist/packages/ofd-core/dist/font.js.map +1 -0
  40. package/dist/packages/ofd-core/dist/index.js +6 -0
  41. package/dist/packages/ofd-core/dist/number.js +13 -0
  42. package/dist/packages/ofd-core/dist/number.js.map +1 -0
  43. package/dist/packages/ofd-core/dist/page-objects.js +181 -0
  44. package/dist/packages/ofd-core/dist/page-objects.js.map +1 -0
  45. package/dist/packages/ofd-core/dist/parse.js +65 -0
  46. package/dist/packages/ofd-core/dist/parse.js.map +1 -0
  47. package/dist/packages/ofd-core/dist/render.js +361 -0
  48. package/dist/packages/ofd-core/dist/render.js.map +1 -0
  49. package/dist/packages/ofd-core/dist/xml.js +199 -0
  50. package/dist/packages/ofd-core/dist/xml.js.map +1 -0
  51. package/dist/packages/ofd-core/dist/zip.js +93 -0
  52. package/dist/packages/ofd-core/dist/zip.js.map +1 -0
  53. package/dist/style.d.ts +1 -1
  54. package/dist/style.js +1 -1
  55. package/dist/types/batch-edit.d.ts +6 -0
  56. package/dist/types/file-viewer.d.ts +1 -1
  57. package/dist/types/index.d.ts +3 -3
  58. package/dist/types/table-editor.d.ts +28 -7
  59. package/dist/types/tip.d.ts +5 -1
  60. package/package.json +8 -7
  61. package/src/components/batch-edit/__test__/batch-edit.test.ts +191 -4
  62. package/src/components/batch-edit/batch-edit-form.vue +17 -3
  63. package/src/components/batch-edit/batch-edit-list.vue +2 -1
  64. package/src/components/batch-edit/batch-edit.vue +22 -4
  65. package/src/components/batch-edit/style.scss +20 -0
  66. package/src/components/batch-edit/style.ts +1 -0
  67. package/src/components/batch-edit/use-dialog-effect.ts +9 -3
  68. package/src/components/batch-edit/use-edit-state.ts +32 -4
  69. package/src/components/batch-edit/use-handlers.ts +10 -0
  70. package/src/components/batch-edit/use-shortcut-key.ts +6 -2
  71. package/src/components/file-viewer/__test__/helper.test.ts +13 -0
  72. package/src/components/file-viewer/file-viewer.vue +23 -16
  73. package/src/components/file-viewer/helper.ts +2 -0
  74. package/src/components/file-viewer/previewers/ofd-previewer.vue +216 -0
  75. package/src/components/file-viewer/style.scss +33 -0
  76. package/src/components/table-editor/__test__/table-editor.test.ts +471 -0
  77. package/src/components/table-editor/style.scss +42 -4
  78. package/src/components/table-editor/table-editor.vue +265 -38
  79. package/src/components/tip/style.scss +15 -0
  80. package/src/components/tip/tip.vue +1 -1
  81. package/src/types/batch-edit.ts +6 -0
  82. package/src/types/file-viewer.ts +1 -1
  83. package/src/types/table-editor.ts +29 -7
  84. package/src/types/tip.ts +6 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","names":[],"sources":["../../../../../ofd-core/dist/render.js"],"sourcesContent":["import { OfdParseError } from \"./error.js\";\nimport { IDENTITY_MATRIX, multiplyMatrix } from \"./ctm.js\";\nimport { joinZipPath } from \"./xml.js\";\nimport { resolveContentLocation } from \"./parse.js\";\nimport { formatNumber, roundTo } from \"./number.js\";\nimport { glyphPathD, parseEmbeddedFont } from \"./font.js\";\nimport { parsePageContent } from \"./page-objects.js\";\n//#region src/render.ts\n/**\n* 逐页 SVG 输出(P2 渲染内核出口)。\n*\n* 页面物理尺寸按 OFD 毫米 → CSS 像素换算(96dpi),内容坐标系保持 OFD 原始\n* 毫米单位(通过 viewBox 缩放),坐标与文档声明一一对应,便于断言与调试。\n* 页与页相互独立、可单独调用,供上层做懒渲染 / 虚拟滚动。\n*/\n/** CSS 约定 96px = 1in = 25.4mm */\nconst PX_PER_MM = 96 / 25.4;\n/** 对象未声明填充色时的默认色(GB/T 33190 未声明时文字按黑色呈现,Fill 路径同) */\nconst DEFAULT_FILL = \"#000\";\n/** 输出指定文档指定页的完整 SVG 字符串 */\nasync function pageToSvg(zip, container, documentIndex, pageIndex) {\n\tconst doc = container.docs[documentIndex];\n\tif (!doc) throw new OfdParseError(\"out-of-range\", `文档序号 ${documentIndex} 超出范围(容器共 ${container.docs.length} 个文档)`);\n\tconst page = doc.pages[pageIndex];\n\tif (!page) throw new OfdParseError(\"out-of-range\", `页序号 ${pageIndex} 超出范围(文档 ${documentIndex} 共 ${doc.pages.length} 页)`);\n\tconst content = parsePageContent(await zip.text(page.location), page.location);\n\tconst size = page.size ?? doc.pageSize ?? {\n\t\twidth: 210,\n\t\theight: 297\n\t};\n\tconst context = {\n\t\tzip,\n\t\tdoc,\n\t\tfonts: /* @__PURE__ */ new Map(),\n\t\ttemplateContents: /* @__PURE__ */ new Map()\n\t};\n\tconst renderedTemplates = await Promise.all(content.templateRefs.map((ref) => renderTemplateRef(ref, context, [content.objectsById], /* @__PURE__ */ new Set())));\n\tconst background = [];\n\tconst foreground = [];\n\tconst templateFrames = [];\n\tfor (const rendered of renderedTemplates) {\n\t\tif (rendered.background !== \"\") background.push(rendered.background);\n\t\tif (rendered.foreground !== \"\") foreground.push(rendered.foreground);\n\t\ttemplateFrames.push(rendered.frames);\n\t}\n\tconst pageFrames = [content.objectsById, ...templateFrames.flat()];\n\tconst layers = await Promise.all(content.layers.map((layer) => renderLayer(layer, context, pageFrames)));\n\treturn `<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"${formatNumber(roundTo(size.width * PX_PER_MM, 2))}px\" height=\"${formatNumber(roundTo(size.height * PX_PER_MM, 2))}px\" viewBox=\"0 0 ${formatNumber(size.width)} ${formatNumber(size.height)}\">${background.join(\"\")}${layers.join(\"\")}${foreground.join(\"\")}</svg>`;\n}\n/** 渲染单个图层:对象按声明顺序叠加,空图层不输出外壳 */\nasync function renderLayer(layer, context, frames) {\n\tconst rendered = (await Promise.all(layer.objects.map((object) => renderObject(object, IDENTITY_MATRIX, null, context, /* @__PURE__ */ new Set(), {\n\t\tframes,\n\t\tdrawParamId: layer.drawParamId\n\t})))).join(\"\");\n\tif (rendered === \"\") return \"\";\n\treturn `<g${layer.type === null ? \"\" : ` data-ofd-layer=\"${layer.type}\"`}>${rendered}</g>`;\n}\n/**\n* 按引用渲染一个模板页:自身引用的模板先于其内容(背景)或后于其内容(前景)\n* 展开,与页面同规则;以内容文件路径判环,递归引用直接断开。\n*/\nasync function renderTemplateRef(ref, context, outerFrames, visiting) {\n\tconst baseLocation = (ref.templateId === null ? void 0 : context.doc.templates.find((template) => template.id === ref.templateId))?.location ?? null;\n\tif (baseLocation === null) return {\n\t\tbackground: \"\",\n\t\tforeground: \"\",\n\t\tframes: []\n\t};\n\tconst location = resolveContentLocation(context.doc.dir, baseLocation);\n\tif (visiting.has(location)) return {\n\t\tbackground: \"\",\n\t\tforeground: \"\",\n\t\tframes: []\n\t};\n\tconst content = await loadTemplateContent(context, location);\n\tconst frames = [content.objectsById, ...outerFrames];\n\tconst nextVisiting = new Set(visiting).add(location);\n\tconst innerRendered = await Promise.all(content.templateRefs.map((innerRef) => renderTemplateRef(innerRef, context, frames, nextVisiting)));\n\tconst innerBackground = [];\n\tconst innerForeground = [];\n\tfor (const rendered of innerRendered) {\n\t\tinnerBackground.push(rendered.background);\n\t\tinnerForeground.push(rendered.foreground);\n\t}\n\tconst ownLayers = (await Promise.all(content.layers.map((layer) => renderLayer(layer, context, frames)))).join(\"\");\n\tconst bundle = innerBackground.join(\"\") + ownLayers + innerForeground.join(\"\");\n\treturn ref.zOrder === \"foreground\" ? {\n\t\tbackground: \"\",\n\t\tforeground: bundle,\n\t\tframes\n\t} : {\n\t\tbackground: bundle,\n\t\tforeground: \"\",\n\t\tframes\n\t};\n}\n/** 加载并解析模板页内容;同一页内重复或递归引用复用解析结果 */\nasync function loadTemplateContent(context, location) {\n\tconst cached = context.templateContents.get(location);\n\tif (cached) return cached;\n\tconst content = parsePageContent(await context.zip.text(location), location);\n\tcontext.templateContents.set(location, content);\n\treturn content;\n}\n/** 渲染单个对象:CTM 链 + Boundary 定位外壳,内容坐标相对 Boundary 原点 */\nasync function renderObject(object, parentCtm, boundaryOverride, context, visiting, scope) {\n\tif (object.id && visiting.has(object.id)) return \"\";\n\tconst ctm = object.ctm ? multiplyMatrix(parentCtm, object.ctm) : parentCtm;\n\tif (object.kind === \"composite\") return renderComposite(object, ctm, context, visiting, scope);\n\tconst boundary = boundaryOverride ?? object.boundary;\n\tconst inner = await renderContent(object, boundary, ctm, context, scope);\n\tif (inner === \"\") return \"\";\n\tconst transform = groupTransform(ctm, boundary);\n\treturn `<g${transform ? ` transform=\"${transform}\"` : \"\"}>${inner}</g>`;\n}\nasync function renderContent(object, boundary, ctm, context, scope) {\n\tswitch (object.kind) {\n\t\tcase \"text\": return renderText(object, context, scope);\n\t\tcase \"image\": return renderImage(object, boundary, ctm, context);\n\t\tcase \"path\": return renderPath(object, context, scope);\n\t}\n}\n/** 复合对象:递归渲染被引用对象,CTM 链向下继承,循环引用直接断开 */\nasync function renderComposite(object, parentCtm, context, visiting, scope) {\n\tconst referenced = findReferencedObject(object, scope);\n\tif (!referenced) return \"\";\n\tconst nextVisiting = new Set(visiting);\n\tif (object.id) nextVisiting.add(object.id);\n\treturn renderObject(referenced, parentCtm, object.boundary, context, nextVisiting, scope);\n}\n/** 复合对象引用查找:当前内容域优先,未命中再沿外层内容域兜底 */\nfunction findReferencedObject(object, scope) {\n\tif (object.referenceId === null) return void 0;\n\tfor (const frame of scope.frames) {\n\t\tconst referenced = frame.get(object.referenceId);\n\t\tif (referenced) return referenced;\n\t}\n}\n/** 文本渲染:声明内嵌字体(Font@FontFile)时按 glyph 轮廓输出 path,否则回退系统字体 text */\nasync function renderText(object, context, scope) {\n\tconst draw = resolveDrawAttributes(object.drawParamId ?? scope.drawParamId, context);\n\tconst fill = object.fillColor ?? draw.fillColor ?? DEFAULT_FILL;\n\tconst font = await loadEmbeddedFont(object.fontId, context);\n\tif (!font || object.fontSize === null) return renderSystemFontText(object, fill, context);\n\tconst fontSize = object.fontSize;\n\tconst parts = [];\n\tlet baseIndex = 0;\n\tfor (const code of object.codes) {\n\t\tconst part = textCodePathD(font, code, fontSize, object.glyphSubstitutions, baseIndex);\n\t\tif (part !== \"\") parts.push(part);\n\t\tbaseIndex += code.text.length;\n\t}\n\tconst d = parts.join(\" \");\n\tif (d === \"\") return object.codes.some((code) => code.text.length > 0) ? renderSystemFontText(object, fill, context) : \"\";\n\treturn `<path d=\"${d}\" fill=\"${fill}\"/>`;\n}\n/** 加载 TextObject@FontID 声明的内嵌 TTF;缺失或损坏返回 null(不阻断整页渲染) */\nasync function loadEmbeddedFont(fontId, context) {\n\tif (fontId === null) return null;\n\tconst cached = context.fonts.get(fontId);\n\tif (cached !== void 0) return cached;\n\tconst decl = context.doc.resources.fonts.find((font) => font.id === fontId);\n\tlet font = null;\n\tif (decl?.fontFile) try {\n\t\tfont = parseEmbeddedFont(await context.zip.read(joinZipPath(context.doc.dir, decl.fontFile)), decl.fontFile);\n\t} catch {\n\t\tfont = null;\n\t}\n\tcontext.fonts.set(fontId, font);\n\treturn font;\n}\n/**\n* 单个 TextCode 的 glyph 路径:从 X/Y 基线原点起笔逐字排布。\n* DeltaX/DeltaY 按标准是「相对前一个字符的位移」,声明时替代字形步进宽度。\n* 字形来源优先取 CGTransform 替换序号(子集字体无 cmap 时的唯一映射),\n* 其次 cmap 码点映射;两者都未命中时跳过该字符的轮廓、仅按位移推进。\n*/\nfunction textCodePathD(font, code, fontSize, substitutions, baseIndex) {\n\tconst scale = fontSize / font.unitsPerEm;\n\tconst parts = [];\n\tlet penX = code.x ?? 0;\n\tlet penY = code.y ?? 0;\n\tlet dxIndex = 0;\n\tlet dyIndex = 0;\n\tlet charIndex = 0;\n\tfor (const char of code.text) {\n\t\tconst gid = substitutedGlyphId(substitutions, baseIndex + charIndex) ?? font.glyphIndexOf(char.codePointAt(0));\n\t\tif (gid !== null) {\n\t\t\tconst d = glyphPathD(font, gid, fontSize, penX, penY);\n\t\t\tif (d !== \"\") parts.push(d);\n\t\t}\n\t\tconst deltaX = dxIndex < code.deltaX.length ? code.deltaX[dxIndex++] : null;\n\t\tpenX += deltaX ?? (gid !== null ? font.advanceWidth(gid) * scale : 0);\n\t\tconst deltaY = dyIndex < code.deltaY.length ? code.deltaY[dyIndex++] : null;\n\t\tpenY += deltaY ?? 0;\n\t\tcharIndex++;\n\t}\n\treturn parts.join(\" \");\n}\n/** 字形替换查找:字符落在声明区间时取 Glyphs 中对应序号,合字耗尽或未覆盖返回 null */\nfunction substitutedGlyphId(substitutions, charIndex) {\n\tfor (const substitution of substitutions) if (charIndex >= substitution.codePosition && charIndex < substitution.codePosition + substitution.codeCount) {\n\t\tconst offset = charIndex - substitution.codePosition;\n\t\treturn offset < substitution.glyphIds.length ? substitution.glyphIds[offset] : null;\n\t}\n\treturn null;\n}\n/** 无内嵌字体可用时的系统字体回退:保留 P2 的 text 输出与文字内容 */\nfunction renderSystemFontText(object, fill, context) {\n\tconst fontFamily = resolveFontFamily(object.fontId, context);\n\treturn object.codes.map((code) => {\n\t\treturn `<text ${[\n\t\t\t\"xml:space=\\\"preserve\\\"\",\n\t\t\tcodePositionAttr(\"x\", code.x, code.text.length, code.deltaX),\n\t\t\tcodePositionAttr(\"y\", code.y, code.text.length, code.deltaY),\n\t\t\tattr(\"font-size\", object.fontSize),\n\t\t\tfontFamily === null ? null : `font-family=\"${escapeXml(fontFamily)}\"`,\n\t\t\t`fill=\"${fill}\"`\n\t\t].filter((value) => value !== null).join(\" \")}>${escapeXml(code.text)}</text>`;\n\t}).join(\"\");\n}\n/**\n* TextCode 位移转 SVG 逐字符坐标:DeltaX/DeltaY 是相邻字符间的绝对步长\n* (替代字形自然步进),而 SVG 的 dx/dy 是在自然步进上的附加量,语义不同,\n* 这里换算成绝对坐标列表;位移未覆盖的字符交由自然排布。\n*/\nfunction codePositionAttr(name, start, charCount, deltas) {\n\tif (start === null && deltas.length === 0) return null;\n\tconst positions = [start ?? 0];\n\tconst covered = Math.min(charCount - 1, deltas.length);\n\tfor (let index = 0; index < covered; index++) positions.push(positions[index] + deltas[index]);\n\treturn positions.length === 1 ? `${name}=\"${formatNumber(positions[0])}\"` : `${name}=\"${positions.map(formatNumber).join(\" \")}\"`;\n}\nfunction resolveFontFamily(fontId, context) {\n\tif (!fontId) return null;\n\treturn context.doc.resources.fonts.find((font) => font.id === fontId)?.fontName ?? null;\n}\n/**\n* 图片:解析 MultiMedia 声明并读资源字节,缺资源或不可识别的媒体类型跳过(不阻断整页)。\n* Type 兼容标准单字母 'g' 与主流产出的 'Image' 拼写。\n*/\nasync function renderImage(object, boundary, ctm, context) {\n\tconst media = object.resourceId === null ? void 0 : context.doc.resources.medias.find((item) => item.id === object.resourceId);\n\tconst location = media?.location;\n\tconst type = media?.type?.toLowerCase();\n\tif (!location || type !== void 0 && type !== \"g\" && type !== \"image\") return \"\";\n\tlet bytes;\n\ttry {\n\t\tbytes = await context.zip.read(joinZipPath(context.doc.dir, location));\n\t} catch {\n\t\treturn \"\";\n\t}\n\tconst mime = sniffImageMime(bytes);\n\tif (!mime) return \"\";\n\tconst content = boundary === null ? null : imageContentSize(boundary, ctm);\n\treturn `<image${content === null ? \"\" : ` width=\"${formatNumber(content.width)}\" height=\"${formatNumber(content.height)}\"`} href=\"data:${mime};base64,${toBase64(bytes)}\"/>`;\n}\n/**\n* 图片内容盒尺寸:无缩放 CTM 时 Boundary 即内容盒;带缩放 CTM 的产出\n* (WPS / 新版数电发票实证)图片内容为 [0,1] 单位盒,尺寸与定位由 CTM 给出,\n* Boundary 只提供平移原点(WPS 写最终包围盒、数电票二维码写整页盒,均不参与定尺寸)。\n*/\nfunction imageContentSize(boundary, ctm) {\n\tif (!hasScaleComponent(ctm)) return {\n\t\twidth: boundary.width,\n\t\theight: boundary.height\n\t};\n\treturn {\n\t\twidth: 1,\n\t\theight: 1\n\t};\n}\n/** 按魔数识别可渲染的图片媒体类型;多帧格式(GIF/APNG)由展示端取首帧 */\nfunction sniffImageMime(bytes) {\n\tif (bytes.length >= 4 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) return \"image/png\";\n\tif (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return \"image/jpeg\";\n\tif (bytes.length >= 3 && bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70) return \"image/gif\";\n\tif (bytes.length >= 2 && bytes[0] === 66 && bytes[1] === 77) return \"image/bmp\";\n\tif (bytes.length >= 12 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) return \"image/webp\";\n\treturn null;\n}\nfunction toBase64(bytes) {\n\tlet binary = \"\";\n\tconst chunkSize = 32768;\n\tfor (let offset = 0; offset < bytes.length; offset += chunkSize) binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));\n\treturn btoa(binary);\n}\n/** 对象生效绘制参数:自身 FillColor/StrokeColor/LineWidth 声明优先于 DrawParam 继承链 */\nfunction resolveDrawAttributes(drawParamId, context) {\n\tconst chain = [];\n\tconst visited = /* @__PURE__ */ new Set();\n\tlet current = drawParamId === null ? void 0 : findDrawParam(drawParamId, context);\n\twhile (current && !visited.has(current.id)) {\n\t\tvisited.add(current.id);\n\t\tchain.unshift(current);\n\t\tcurrent = current.relative === null ? void 0 : findDrawParam(current.relative, context);\n\t}\n\tlet fillColor = null;\n\tlet strokeColor = null;\n\tlet lineWidth = null;\n\tfor (const declaration of chain) {\n\t\tfillColor ??= declaration.fillColor;\n\t\tstrokeColor ??= declaration.strokeColor;\n\t\tlineWidth ??= declaration.lineWidth;\n\t}\n\treturn {\n\t\tfillColor,\n\t\tstrokeColor,\n\t\tlineWidth\n\t};\n}\nfunction findDrawParam(id, context) {\n\treturn context.doc.resources.drawParams.find((param) => param.id === id);\n}\nfunction renderPath(object, context, scope) {\n\tconst d = pathD(object.commands);\n\tif (d === \"\") return \"\";\n\tconst draw = resolveDrawAttributes(object.drawParamId ?? scope.drawParamId, context);\n\tconst strokeColor = object.strokeColor ?? draw.strokeColor;\n\tconst fill = object.fillColor ?? draw.fillColor ?? (object.fill ? DEFAULT_FILL : \"none\");\n\treturn `<path ${[\n\t\t`d=\"${d}\"`,\n\t\t`fill=\"${fill}\"`,\n\t\tstrokeColor === null ? null : `stroke=\"${strokeColor}\"`,\n\t\tattr(\"stroke-width\", object.lineWidth ?? draw.lineWidth),\n\t\tlistAttr(\"stroke-dasharray\", object.dashPattern)\n\t].filter((value) => value !== null).join(\" \")}/>`;\n}\nfunction pathD(commands) {\n\treturn commands.map((command) => command.type === \"Z\" ? \"Z\" : `${command.type === \"B\" ? \"Q\" : command.type} ${command.points.map(formatNumber).join(\" \")}`).join(\" \");\n}\n/** 对象外壳 transform:CTM 矩阵 + 平移到 Boundary 原点,单位矩阵不输出 */\nfunction groupTransform(ctm, boundary) {\n\tconst matrix = isIdentityMatrix(ctm) ? null : `matrix(${ctm.map(formatNumber).join(\" \")})`;\n\tif (!boundary) return matrix ?? \"\";\n\tconst translate = `translate(${formatNumber(boundary.x)} ${formatNumber(boundary.y)})`;\n\tif (hasScaleComponent(ctm)) return matrix ? `${translate} ${matrix}` : translate;\n\treturn matrix ? `${matrix} ${translate}` : translate;\n}\n/** CTM 是否带缩放分量(旋转/切变的轴长为 1,缩放会偏离 1) */\nfunction hasScaleComponent(ctm) {\n\treturn Math.abs(Math.hypot(ctm[0], ctm[1]) - 1) > 1e-6 || Math.abs(Math.hypot(ctm[2], ctm[3]) - 1) > 1e-6;\n}\nfunction isIdentityMatrix(matrix) {\n\treturn matrix[0] === 1 && matrix[1] === 0 && matrix[2] === 0 && matrix[3] === 1 && matrix[4] === 0 && matrix[5] === 0;\n}\nfunction attr(name, value) {\n\tif (value === null) return null;\n\treturn `${name}=\"${typeof value === \"number\" ? formatNumber(value) : escapeXml(value)}\"`;\n}\nfunction listAttr(name, values) {\n\treturn values.length === 0 ? null : `${name}=\"${values.map(formatNumber).join(\" \")}\"`;\n}\nfunction escapeXml(text) {\n\treturn text.replaceAll(\"&\", \"&amp;\").replaceAll(\"<\", \"&lt;\").replaceAll(\">\", \"&gt;\").replaceAll(\"\\\"\", \"&quot;\");\n}\n//#endregion\nexport { pageToSvg };\n\n//# sourceMappingURL=render.js.map"],"mappings":"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"}
@@ -0,0 +1,199 @@
1
+ import { OfdParseError } from "./error.js";
2
+ import { parseNumberList } from "./ctm.js";
3
+ import { parseOfdColor } from "./color.js";
4
+ //#region ../ofd-core/dist/xml.js
5
+ function childElements(element) {
6
+ const out = [];
7
+ for (let i = 0; i < element.childNodes.length; i++) {
8
+ const node = element.childNodes[i];
9
+ if (node && node.nodeType === 1) out.push(node);
10
+ }
11
+ return out;
12
+ }
13
+ function localNameOf(element) {
14
+ if (element.localName) return element.localName;
15
+ const tag = element.nodeName;
16
+ return tag.includes(":") ? tag.slice(tag.indexOf(":") + 1) : tag;
17
+ }
18
+ function childrenNamed(element, name) {
19
+ return childElements(element).filter((child) => localNameOf(child) === name);
20
+ }
21
+ function firstChildNamed(element, name) {
22
+ return childrenNamed(element, name)[0] ?? null;
23
+ }
24
+ function childText(element, name) {
25
+ return firstChildNamed(element, name)?.textContent ?? null;
26
+ }
27
+ function normalizedText(value) {
28
+ const text = value?.trim();
29
+ return text ? text : null;
30
+ }
31
+ function parseXml(xml, source) {
32
+ let doc;
33
+ try {
34
+ doc = new DOMParser().parseFromString(xml, "application/xml");
35
+ } catch (cause) {
36
+ throw new OfdParseError("invalid-xml", `${source} 不是合法的 XML`, { cause });
37
+ }
38
+ if (doc.getElementsByTagName("parsererror").length > 0) throw new OfdParseError("invalid-xml", `${source} 不是合法的 XML`);
39
+ return doc;
40
+ }
41
+ function rootElementOf(doc, names, source) {
42
+ const expected = typeof names === "string" ? [names] : names;
43
+ const root = doc.documentElement;
44
+ const lowered = expected.map((name) => name.toLowerCase());
45
+ if (!root || !lowered.includes(localNameOf(root).toLowerCase())) throw new OfdParseError("invalid-structure", `${source} 根节点不是 ${expected.join(" / ")}`);
46
+ return root;
47
+ }
48
+ /** 解析 OFD.xml:每个 DocBody 产出一条入口,支持多文档容器 */
49
+ function parseOfdRoot(xml, source = "OFD.xml") {
50
+ return childrenNamed(rootElementOf(parseXml(xml, source), "Ofd", source), "DocBody").map((body) => {
51
+ const docRoot = normalizedText(childText(body, "DocRoot"));
52
+ if (!docRoot) throw new OfdParseError("invalid-structure", `${source} 中 DocBody 缺少 DocRoot`);
53
+ const info = firstChildNamed(body, "DocInfo");
54
+ return {
55
+ docRoot,
56
+ info: {
57
+ docId: info ? normalizedText(childText(info, "DocID")) : null,
58
+ title: info ? normalizedText(childText(info, "Title")) : null
59
+ }
60
+ };
61
+ });
62
+ }
63
+ /** 解析 Document.xml:默认页尺寸、公共资源引用、模板页声明、页面树 */
64
+ function parseDocumentXml(xml, source) {
65
+ const root = rootElementOf(parseXml(xml, source), "Document", source);
66
+ const commonData = firstChildNamed(root, "CommonData");
67
+ const pages = firstChildNamed(root, "Pages");
68
+ return {
69
+ pageSize: commonData ? parsePageSize(commonData) ?? physicalBoxSize(commonData, "PageArea") : null,
70
+ resLocation: resDeclarationLocation(root, commonData, "DocumentRes"),
71
+ publicResLocation: resDeclarationLocation(root, commonData, "PublicRes"),
72
+ templates: commonData ? childrenNamed(commonData, "TemplatePage").map((template) => ({
73
+ id: template.getAttribute("ID"),
74
+ location: normalizedText(template.getAttribute("BaseLoc") ?? template.textContent)
75
+ })) : [],
76
+ pageLocations: pages ? childrenNamed(pages, "Page").map((page) => normalizedText(page.getAttribute("BaseLoc"))).filter((value) => value !== null) : []
77
+ };
78
+ }
79
+ /**
80
+ * 资源声明路径兼容两种产出形态:声明元素挂在 Document 根或 CommonData 下,
81
+ * 路径写在 ResLoc 属性或元素文本中(WPS / 数科 / 数电发票产出均为文本形态)。
82
+ */
83
+ function resDeclarationLocation(root, commonData, name) {
84
+ const node = firstChildNamed(root, name) ?? (commonData && firstChildNamed(commonData, name));
85
+ if (!node) return null;
86
+ return normalizedText(node.getAttribute("ResLoc")) ?? normalizedText(node.textContent);
87
+ }
88
+ /** 物理盒尺寸兜底("x y w h" 取宽高);主流生成器以 PhysicalBox 代替 PageWidth/PageHeight */
89
+ function physicalBoxSize(scope, wrapper) {
90
+ const container = firstChildNamed(scope, wrapper);
91
+ const box = container ? firstChildNamed(container, "PhysicalBox") : null;
92
+ const numbers = parseNumberList(box?.textContent ?? null);
93
+ return numbers.length === 4 ? {
94
+ width: numbers[2],
95
+ height: numbers[3]
96
+ } : null;
97
+ }
98
+ /** 解析 DocumentRes.xml / PublicRes.xml:字体、多媒体资源与绘制参数声明 */
99
+ function parseDocumentRes(xml, source) {
100
+ const root = rootElementOf(parseXml(xml, source), "Res", source);
101
+ const baseLoc = normalizedText(root.getAttribute("BaseLoc"));
102
+ const fonts = [];
103
+ const medias = [];
104
+ const drawParams = [];
105
+ for (const group of childrenNamed(root, "Fonts")) for (const font of childrenNamed(group, "Font")) {
106
+ const id = font.getAttribute("ID");
107
+ if (id !== null) fonts.push({
108
+ id,
109
+ fontName: normalizedText(font.getAttribute("FontName")),
110
+ fontFile: fontFileLocation(baseLoc, font)
111
+ });
112
+ }
113
+ for (const group of childrenNamed(root, "MultiMedias")) for (const media of childrenNamed(group, "MultiMedia")) {
114
+ const id = media.getAttribute("ID");
115
+ if (id !== null) medias.push({
116
+ id,
117
+ type: media.getAttribute("Type"),
118
+ location: normalizedText(media.getAttribute("ResLoc")) ?? mediaFileLocation(baseLoc, media)
119
+ });
120
+ }
121
+ for (const group of childrenNamed(root, "DrawParams")) for (const param of childrenNamed(group, "DrawParam")) {
122
+ const id = param.getAttribute("ID");
123
+ if (id !== null) drawParams.push({
124
+ id,
125
+ lineWidth: parseNumber(param.getAttribute("LineWidth")),
126
+ relative: normalizedText(param.getAttribute("Relative")),
127
+ fillColor: declaredColor(param, "FillColor"),
128
+ strokeColor: declaredColor(param, "StrokeColor")
129
+ });
130
+ }
131
+ return {
132
+ fonts,
133
+ medias,
134
+ drawParams
135
+ };
136
+ }
137
+ /** DrawParam 子元素颜色:<FillColor Value="128 0 0"/> 按 Value 属性解析 */
138
+ function declaredColor(param, name) {
139
+ return parseOfdColor(firstChildNamed(param, name)?.getAttribute("Value") ?? null);
140
+ }
141
+ /**
142
+ * 字体文件位置:FontFile 兼容属性与子元素两种声明(新版数电发票实证为子元素),
143
+ * 路径相对资源声明根的 BaseLoc 解析,未声明 BaseLoc 时相对文档根。
144
+ */
145
+ function fontFileLocation(baseLoc, font) {
146
+ const file = normalizedText(font.getAttribute("FontFile")) ?? normalizedText(childText(font, "FontFile"));
147
+ return file === null ? null : joinZipPath(baseLoc ?? "", file);
148
+ }
149
+ /** 媒体位置兜底:MediaFile 子元素声明文件名,相对资源声明根的 BaseLoc 解析 */
150
+ function mediaFileLocation(baseLoc, media) {
151
+ const file = normalizedText(firstChildNamed(media, "MediaFile")?.textContent ?? null);
152
+ return file === null ? null : joinZipPath(baseLoc ?? "", file);
153
+ }
154
+ /**
155
+ * 拼接并规范化容器内路径:去空段与 './',统一 '/' 分隔(页面定位、图片资源定位共用)。
156
+ * 段以 '/' 开头时按容器绝对路径处理(个别产出在相对文档根的位置写绝对路径)。
157
+ */
158
+ function joinZipPath(...segments) {
159
+ const parts = [];
160
+ for (const segment of segments) {
161
+ if (segment.startsWith("/")) parts.length = 0;
162
+ for (const piece of segment.split("/")) if (piece !== "" && piece !== ".") parts.push(piece);
163
+ }
164
+ return parts.join("/");
165
+ }
166
+ /** 解析 Page.xml:页面尺寸覆盖与图层声明 */
167
+ function parsePageXml(xml, source) {
168
+ const root = rootElementOf(parseXml(xml, source), "Page", source);
169
+ const commonData = firstChildNamed(root, "CommonData");
170
+ const layerParent = firstChildNamed(root, "Content") ?? root;
171
+ return {
172
+ size: (commonData ? parsePageSize(commonData) ?? physicalBoxSize(commonData, "PageArea") : null) ?? physicalBoxSize(root, "Area"),
173
+ layers: childrenNamed(layerParent, "Layer").map((layer) => ({
174
+ id: layer.getAttribute("ID"),
175
+ type: parseLayerType(layer.getAttribute("Type"))
176
+ }))
177
+ };
178
+ }
179
+ function parsePageSize(commonData) {
180
+ const width = parseNumber(childText(commonData, "PageWidth"));
181
+ const height = parseNumber(childText(commonData, "PageHeight"));
182
+ return width !== null && height !== null ? {
183
+ width,
184
+ height
185
+ } : null;
186
+ }
187
+ function parseNumber(value) {
188
+ if (value === null || value.trim() === "") return null;
189
+ const parsed = Number(value);
190
+ return Number.isFinite(parsed) ? parsed : null;
191
+ }
192
+ function parseLayerType(value) {
193
+ const lowered = value?.toLowerCase();
194
+ return lowered === "background" || lowered === "body" || lowered === "foreground" || lowered === "annotation" ? lowered : null;
195
+ }
196
+ //#endregion
197
+ export { childElements, childrenNamed, firstChildNamed, joinZipPath, localNameOf, parseDocumentRes, parseDocumentXml, parseLayerType, parseOfdRoot, parsePageXml, parseXml, rootElementOf };
198
+
199
+ //# sourceMappingURL=xml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xml.js","names":[],"sources":["../../../../../ofd-core/dist/xml.js"],"sourcesContent":["import { OfdParseError } from \"./error.js\";\nimport { parseNumberList } from \"./ctm.js\";\nimport { parseOfdColor } from \"./color.js\";\n//#region src/xml.ts\nfunction childElements(element) {\n\tconst out = [];\n\tfor (let i = 0; i < element.childNodes.length; i++) {\n\t\tconst node = element.childNodes[i];\n\t\tif (node && node.nodeType === 1) out.push(node);\n\t}\n\treturn out;\n}\nfunction localNameOf(element) {\n\tif (element.localName) return element.localName;\n\tconst tag = element.nodeName;\n\treturn tag.includes(\":\") ? tag.slice(tag.indexOf(\":\") + 1) : tag;\n}\nfunction childrenNamed(element, name) {\n\treturn childElements(element).filter((child) => localNameOf(child) === name);\n}\nfunction firstChildNamed(element, name) {\n\treturn childrenNamed(element, name)[0] ?? null;\n}\nfunction childText(element, name) {\n\treturn firstChildNamed(element, name)?.textContent ?? null;\n}\nfunction normalizedText(value) {\n\tconst text = value?.trim();\n\treturn text ? text : null;\n}\nfunction parseXml(xml, source) {\n\tlet doc;\n\ttry {\n\t\tdoc = new DOMParser().parseFromString(xml, \"application/xml\");\n\t} catch (cause) {\n\t\tthrow new OfdParseError(\"invalid-xml\", `${source} 不是合法的 XML`, { cause });\n\t}\n\tif (doc.getElementsByTagName(\"parsererror\").length > 0) throw new OfdParseError(\"invalid-xml\", `${source} 不是合法的 XML`);\n\treturn doc;\n}\nfunction rootElementOf(doc, names, source) {\n\tconst expected = typeof names === \"string\" ? [names] : names;\n\tconst root = doc.documentElement;\n\tconst lowered = expected.map((name) => name.toLowerCase());\n\tif (!root || !lowered.includes(localNameOf(root).toLowerCase())) throw new OfdParseError(\"invalid-structure\", `${source} 根节点不是 ${expected.join(\" / \")}`);\n\treturn root;\n}\n/** 解析 OFD.xml:每个 DocBody 产出一条入口,支持多文档容器 */\nfunction parseOfdRoot(xml, source = \"OFD.xml\") {\n\treturn childrenNamed(rootElementOf(parseXml(xml, source), \"Ofd\", source), \"DocBody\").map((body) => {\n\t\tconst docRoot = normalizedText(childText(body, \"DocRoot\"));\n\t\tif (!docRoot) throw new OfdParseError(\"invalid-structure\", `${source} 中 DocBody 缺少 DocRoot`);\n\t\tconst info = firstChildNamed(body, \"DocInfo\");\n\t\treturn {\n\t\t\tdocRoot,\n\t\t\tinfo: {\n\t\t\t\tdocId: info ? normalizedText(childText(info, \"DocID\")) : null,\n\t\t\t\ttitle: info ? normalizedText(childText(info, \"Title\")) : null\n\t\t\t}\n\t\t};\n\t});\n}\n/** 解析 Document.xml:默认页尺寸、公共资源引用、模板页声明、页面树 */\nfunction parseDocumentXml(xml, source) {\n\tconst root = rootElementOf(parseXml(xml, source), \"Document\", source);\n\tconst commonData = firstChildNamed(root, \"CommonData\");\n\tconst pages = firstChildNamed(root, \"Pages\");\n\treturn {\n\t\tpageSize: commonData ? parsePageSize(commonData) ?? physicalBoxSize(commonData, \"PageArea\") : null,\n\t\tresLocation: resDeclarationLocation(root, commonData, \"DocumentRes\"),\n\t\tpublicResLocation: resDeclarationLocation(root, commonData, \"PublicRes\"),\n\t\ttemplates: commonData ? childrenNamed(commonData, \"TemplatePage\").map((template) => ({\n\t\t\tid: template.getAttribute(\"ID\"),\n\t\t\tlocation: normalizedText(template.getAttribute(\"BaseLoc\") ?? template.textContent)\n\t\t})) : [],\n\t\tpageLocations: pages ? childrenNamed(pages, \"Page\").map((page) => normalizedText(page.getAttribute(\"BaseLoc\"))).filter((value) => value !== null) : []\n\t};\n}\n/**\n* 资源声明路径兼容两种产出形态:声明元素挂在 Document 根或 CommonData 下,\n* 路径写在 ResLoc 属性或元素文本中(WPS / 数科 / 数电发票产出均为文本形态)。\n*/\nfunction resDeclarationLocation(root, commonData, name) {\n\tconst node = firstChildNamed(root, name) ?? (commonData && firstChildNamed(commonData, name));\n\tif (!node) return null;\n\treturn normalizedText(node.getAttribute(\"ResLoc\")) ?? normalizedText(node.textContent);\n}\n/** 物理盒尺寸兜底(\"x y w h\" 取宽高);主流生成器以 PhysicalBox 代替 PageWidth/PageHeight */\nfunction physicalBoxSize(scope, wrapper) {\n\tconst container = firstChildNamed(scope, wrapper);\n\tconst box = container ? firstChildNamed(container, \"PhysicalBox\") : null;\n\tconst numbers = parseNumberList(box?.textContent ?? null);\n\treturn numbers.length === 4 ? {\n\t\twidth: numbers[2],\n\t\theight: numbers[3]\n\t} : null;\n}\n/** 解析 DocumentRes.xml / PublicRes.xml:字体、多媒体资源与绘制参数声明 */\nfunction parseDocumentRes(xml, source) {\n\tconst root = rootElementOf(parseXml(xml, source), \"Res\", source);\n\tconst baseLoc = normalizedText(root.getAttribute(\"BaseLoc\"));\n\tconst fonts = [];\n\tconst medias = [];\n\tconst drawParams = [];\n\tfor (const group of childrenNamed(root, \"Fonts\")) for (const font of childrenNamed(group, \"Font\")) {\n\t\tconst id = font.getAttribute(\"ID\");\n\t\tif (id !== null) fonts.push({\n\t\t\tid,\n\t\t\tfontName: normalizedText(font.getAttribute(\"FontName\")),\n\t\t\tfontFile: fontFileLocation(baseLoc, font)\n\t\t});\n\t}\n\tfor (const group of childrenNamed(root, \"MultiMedias\")) for (const media of childrenNamed(group, \"MultiMedia\")) {\n\t\tconst id = media.getAttribute(\"ID\");\n\t\tif (id !== null) medias.push({\n\t\t\tid,\n\t\t\ttype: media.getAttribute(\"Type\"),\n\t\t\tlocation: normalizedText(media.getAttribute(\"ResLoc\")) ?? mediaFileLocation(baseLoc, media)\n\t\t});\n\t}\n\tfor (const group of childrenNamed(root, \"DrawParams\")) for (const param of childrenNamed(group, \"DrawParam\")) {\n\t\tconst id = param.getAttribute(\"ID\");\n\t\tif (id !== null) drawParams.push({\n\t\t\tid,\n\t\t\tlineWidth: parseNumber(param.getAttribute(\"LineWidth\")),\n\t\t\trelative: normalizedText(param.getAttribute(\"Relative\")),\n\t\t\tfillColor: declaredColor(param, \"FillColor\"),\n\t\t\tstrokeColor: declaredColor(param, \"StrokeColor\")\n\t\t});\n\t}\n\treturn {\n\t\tfonts,\n\t\tmedias,\n\t\tdrawParams\n\t};\n}\n/** DrawParam 子元素颜色:<FillColor Value=\"128 0 0\"/> 按 Value 属性解析 */\nfunction declaredColor(param, name) {\n\treturn parseOfdColor(firstChildNamed(param, name)?.getAttribute(\"Value\") ?? null);\n}\n/**\n* 字体文件位置:FontFile 兼容属性与子元素两种声明(新版数电发票实证为子元素),\n* 路径相对资源声明根的 BaseLoc 解析,未声明 BaseLoc 时相对文档根。\n*/\nfunction fontFileLocation(baseLoc, font) {\n\tconst file = normalizedText(font.getAttribute(\"FontFile\")) ?? normalizedText(childText(font, \"FontFile\"));\n\treturn file === null ? null : joinZipPath(baseLoc ?? \"\", file);\n}\n/** 媒体位置兜底:MediaFile 子元素声明文件名,相对资源声明根的 BaseLoc 解析 */\nfunction mediaFileLocation(baseLoc, media) {\n\tconst file = normalizedText(firstChildNamed(media, \"MediaFile\")?.textContent ?? null);\n\treturn file === null ? null : joinZipPath(baseLoc ?? \"\", file);\n}\n/**\n* 拼接并规范化容器内路径:去空段与 './',统一 '/' 分隔(页面定位、图片资源定位共用)。\n* 段以 '/' 开头时按容器绝对路径处理(个别产出在相对文档根的位置写绝对路径)。\n*/\nfunction joinZipPath(...segments) {\n\tconst parts = [];\n\tfor (const segment of segments) {\n\t\tif (segment.startsWith(\"/\")) parts.length = 0;\n\t\tfor (const piece of segment.split(\"/\")) if (piece !== \"\" && piece !== \".\") parts.push(piece);\n\t}\n\treturn parts.join(\"/\");\n}\n/** 解析 Page.xml:页面尺寸覆盖与图层声明 */\nfunction parsePageXml(xml, source) {\n\tconst root = rootElementOf(parseXml(xml, source), \"Page\", source);\n\tconst commonData = firstChildNamed(root, \"CommonData\");\n\tconst layerParent = firstChildNamed(root, \"Content\") ?? root;\n\treturn {\n\t\tsize: (commonData ? parsePageSize(commonData) ?? physicalBoxSize(commonData, \"PageArea\") : null) ?? physicalBoxSize(root, \"Area\"),\n\t\tlayers: childrenNamed(layerParent, \"Layer\").map((layer) => ({\n\t\t\tid: layer.getAttribute(\"ID\"),\n\t\t\ttype: parseLayerType(layer.getAttribute(\"Type\"))\n\t\t}))\n\t};\n}\nfunction parsePageSize(commonData) {\n\tconst width = parseNumber(childText(commonData, \"PageWidth\"));\n\tconst height = parseNumber(childText(commonData, \"PageHeight\"));\n\treturn width !== null && height !== null ? {\n\t\twidth,\n\t\theight\n\t} : null;\n}\nfunction parseNumber(value) {\n\tif (value === null || value.trim() === \"\") return null;\n\tconst parsed = Number(value);\n\treturn Number.isFinite(parsed) ? parsed : null;\n}\nfunction parseLayerType(value) {\n\tconst lowered = value?.toLowerCase();\n\treturn lowered === \"background\" || lowered === \"body\" || lowered === \"foreground\" || lowered === \"annotation\" ? lowered : null;\n}\n//#endregion\nexport { childElements, childrenNamed, firstChildNamed, joinZipPath, localNameOf, parseDocumentRes, parseDocumentXml, parseLayerType, parseOfdRoot, parsePageXml, parseXml, rootElementOf };\n\n//# sourceMappingURL=xml.js.map"],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ import { OfdParseError } from "./error.js";
2
+ //#region ../ofd-core/dist/zip.js
3
+ const EOCD_SIGNATURE = 101010256;
4
+ const CEN_SIGNATURE = 33639248;
5
+ const LOC_SIGNATURE = 67324752;
6
+ const EOCD_LENGTH = 22;
7
+ const CEN_HEADER_LENGTH = 46;
8
+ const LOC_HEADER_LENGTH = 30;
9
+ /** EOCD 注释区最大长度,找 EOCD 时最多向前扫这么多字节 */
10
+ const EOCD_COMMENT_MAX = 65535;
11
+ const STORED_METHOD = 0;
12
+ const DEFLATE_METHOD = 8;
13
+ /** 解析 ZIP 结构(EOCD / 中央目录);条目数据在 read 时才解压 */
14
+ function openOfdZip(data) {
15
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
16
+ const eocdOffset = findEocdOffset(data);
17
+ const records = parseCentralDirectory(data, view, eocdOffset, view.getUint16(eocdOffset + 10, true));
18
+ const byName = new Map(records.map((record) => [record.name.toLowerCase(), record]));
19
+ return {
20
+ entries: records,
21
+ has: (name) => byName.has(name.toLowerCase()),
22
+ read: (name) => readEntry(data, view, byName.get(name.toLowerCase()), name),
23
+ text: async (name) => new TextDecoder().decode(await readEntry(data, view, byName.get(name.toLowerCase()), name))
24
+ };
25
+ }
26
+ function findEocdOffset(data) {
27
+ const minStart = Math.max(0, data.length - EOCD_LENGTH - EOCD_COMMENT_MAX);
28
+ for (let offset = data.length - EOCD_LENGTH; offset >= minStart; offset--) if (readU32(data, offset) === EOCD_SIGNATURE) return offset;
29
+ throw new OfdParseError("not-zip", "未找到 ZIP End of Central Directory,输入不是合法的 ZIP 容器");
30
+ }
31
+ function parseCentralDirectory(data, view, eocdOffset, entryCount) {
32
+ let offset = view.getUint32(eocdOffset + 16, true);
33
+ const records = [];
34
+ for (let index = 0; index < entryCount; index++) {
35
+ if (offset + CEN_HEADER_LENGTH > data.length) throw new OfdParseError("truncated", `中央目录第 ${index} 个条目越界,数据被截断`);
36
+ if (view.getUint32(offset, true) !== CEN_SIGNATURE) throw new OfdParseError("bad-central-directory", `中央目录第 ${index} 个条目签名不合法`);
37
+ const method = view.getUint16(offset + 10, true);
38
+ const compressedSize = view.getUint32(offset + 20, true);
39
+ const size = view.getUint32(offset + 24, true);
40
+ const nameLength = view.getUint16(offset + 28, true);
41
+ const extraLength = view.getUint16(offset + 30, true);
42
+ const commentLength = view.getUint16(offset + 32, true);
43
+ const localHeaderOffset = view.getUint32(offset + 42, true);
44
+ const recordLength = CEN_HEADER_LENGTH + nameLength + extraLength + commentLength;
45
+ if (offset + recordLength > data.length) throw new OfdParseError("truncated", `中央目录第 ${index} 个条目不完整,数据被截断`);
46
+ const name = new TextDecoder().decode(data.subarray(offset + CEN_HEADER_LENGTH, offset + CEN_HEADER_LENGTH + nameLength));
47
+ records.push({
48
+ name,
49
+ method,
50
+ compressedSize,
51
+ size,
52
+ localHeaderOffset
53
+ });
54
+ offset += recordLength;
55
+ }
56
+ return records;
57
+ }
58
+ function readEntry(data, view, record, name) {
59
+ if (!record) throw new OfdParseError("missing-entry", `容器中不存在条目 ${name}`);
60
+ const start = entryDataStart(data, view, record);
61
+ const compressed = data.subarray(start, start + record.compressedSize);
62
+ if (record.method === STORED_METHOD) return Promise.resolve(compressed);
63
+ if (record.method === DEFLATE_METHOD) return inflateRaw(compressed, name);
64
+ return Promise.reject(new OfdParseError("unsupported-compression", `条目 ${name} 使用不支持的压缩方法 ${record.method}`));
65
+ }
66
+ /** 定位条目数据起点:跳过本地文件头(长度以本地头声明的为准) */
67
+ function entryDataStart(data, view, record) {
68
+ const offset = record.localHeaderOffset;
69
+ if (offset + LOC_HEADER_LENGTH > data.length) throw new OfdParseError("truncated", `条目 ${record.name} 的本地文件头越界`);
70
+ if (view.getUint32(offset, true) !== LOC_SIGNATURE) throw new OfdParseError("bad-local-header", `条目 ${record.name} 的本地文件头签名不合法`);
71
+ const start = offset + LOC_HEADER_LENGTH + view.getUint16(offset + 26, true) + view.getUint16(offset + 28, true);
72
+ if (start + record.compressedSize > data.length) throw new OfdParseError("truncated", `条目 ${record.name} 的数据被截断`);
73
+ return start;
74
+ }
75
+ /** 用原生 DecompressionStream 解压 deflate-raw 数据 */
76
+ async function inflateRaw(compressed, name) {
77
+ try {
78
+ const stream = new ReadableStream({ start(controller) {
79
+ controller.enqueue(compressed);
80
+ controller.close();
81
+ } }).pipeThrough(new DecompressionStream("deflate-raw"));
82
+ return new Uint8Array(await new Response(stream).arrayBuffer());
83
+ } catch (cause) {
84
+ throw new OfdParseError("truncated", `条目 ${name} 的 deflate 数据无法解压`, { cause });
85
+ }
86
+ }
87
+ function readU32(data, offset) {
88
+ return (data[offset + 3] << 24 | data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset]) >>> 0;
89
+ }
90
+ //#endregion
91
+ export { openOfdZip };
92
+
93
+ //# sourceMappingURL=zip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zip.js","names":[],"sources":["../../../../../ofd-core/dist/zip.js"],"sourcesContent":["import { OfdParseError } from \"./error.js\";\n//#region src/zip.ts\nconst EOCD_SIGNATURE = 101010256;\nconst CEN_SIGNATURE = 33639248;\nconst LOC_SIGNATURE = 67324752;\nconst EOCD_LENGTH = 22;\nconst CEN_HEADER_LENGTH = 46;\nconst LOC_HEADER_LENGTH = 30;\n/** EOCD 注释区最大长度,找 EOCD 时最多向前扫这么多字节 */\nconst EOCD_COMMENT_MAX = 65535;\nconst STORED_METHOD = 0;\nconst DEFLATE_METHOD = 8;\n/** 解析 ZIP 结构(EOCD / 中央目录);条目数据在 read 时才解压 */\nfunction openOfdZip(data) {\n\tconst view = new DataView(data.buffer, data.byteOffset, data.byteLength);\n\tconst eocdOffset = findEocdOffset(data);\n\tconst records = parseCentralDirectory(data, view, eocdOffset, view.getUint16(eocdOffset + 10, true));\n\tconst byName = new Map(records.map((record) => [record.name.toLowerCase(), record]));\n\treturn {\n\t\tentries: records,\n\t\thas: (name) => byName.has(name.toLowerCase()),\n\t\tread: (name) => readEntry(data, view, byName.get(name.toLowerCase()), name),\n\t\ttext: async (name) => new TextDecoder().decode(await readEntry(data, view, byName.get(name.toLowerCase()), name))\n\t};\n}\nfunction findEocdOffset(data) {\n\tconst minStart = Math.max(0, data.length - EOCD_LENGTH - EOCD_COMMENT_MAX);\n\tfor (let offset = data.length - EOCD_LENGTH; offset >= minStart; offset--) if (readU32(data, offset) === EOCD_SIGNATURE) return offset;\n\tthrow new OfdParseError(\"not-zip\", \"未找到 ZIP End of Central Directory,输入不是合法的 ZIP 容器\");\n}\nfunction parseCentralDirectory(data, view, eocdOffset, entryCount) {\n\tlet offset = view.getUint32(eocdOffset + 16, true);\n\tconst records = [];\n\tfor (let index = 0; index < entryCount; index++) {\n\t\tif (offset + CEN_HEADER_LENGTH > data.length) throw new OfdParseError(\"truncated\", `中央目录第 ${index} 个条目越界,数据被截断`);\n\t\tif (view.getUint32(offset, true) !== CEN_SIGNATURE) throw new OfdParseError(\"bad-central-directory\", `中央目录第 ${index} 个条目签名不合法`);\n\t\tconst method = view.getUint16(offset + 10, true);\n\t\tconst compressedSize = view.getUint32(offset + 20, true);\n\t\tconst size = view.getUint32(offset + 24, true);\n\t\tconst nameLength = view.getUint16(offset + 28, true);\n\t\tconst extraLength = view.getUint16(offset + 30, true);\n\t\tconst commentLength = view.getUint16(offset + 32, true);\n\t\tconst localHeaderOffset = view.getUint32(offset + 42, true);\n\t\tconst recordLength = CEN_HEADER_LENGTH + nameLength + extraLength + commentLength;\n\t\tif (offset + recordLength > data.length) throw new OfdParseError(\"truncated\", `中央目录第 ${index} 个条目不完整,数据被截断`);\n\t\tconst name = new TextDecoder().decode(data.subarray(offset + CEN_HEADER_LENGTH, offset + CEN_HEADER_LENGTH + nameLength));\n\t\trecords.push({\n\t\t\tname,\n\t\t\tmethod,\n\t\t\tcompressedSize,\n\t\t\tsize,\n\t\t\tlocalHeaderOffset\n\t\t});\n\t\toffset += recordLength;\n\t}\n\treturn records;\n}\nfunction readEntry(data, view, record, name) {\n\tif (!record) throw new OfdParseError(\"missing-entry\", `容器中不存在条目 ${name}`);\n\tconst start = entryDataStart(data, view, record);\n\tconst compressed = data.subarray(start, start + record.compressedSize);\n\tif (record.method === STORED_METHOD) return Promise.resolve(compressed);\n\tif (record.method === DEFLATE_METHOD) return inflateRaw(compressed, name);\n\treturn Promise.reject(new OfdParseError(\"unsupported-compression\", `条目 ${name} 使用不支持的压缩方法 ${record.method}`));\n}\n/** 定位条目数据起点:跳过本地文件头(长度以本地头声明的为准) */\nfunction entryDataStart(data, view, record) {\n\tconst offset = record.localHeaderOffset;\n\tif (offset + LOC_HEADER_LENGTH > data.length) throw new OfdParseError(\"truncated\", `条目 ${record.name} 的本地文件头越界`);\n\tif (view.getUint32(offset, true) !== LOC_SIGNATURE) throw new OfdParseError(\"bad-local-header\", `条目 ${record.name} 的本地文件头签名不合法`);\n\tconst start = offset + LOC_HEADER_LENGTH + view.getUint16(offset + 26, true) + view.getUint16(offset + 28, true);\n\tif (start + record.compressedSize > data.length) throw new OfdParseError(\"truncated\", `条目 ${record.name} 的数据被截断`);\n\treturn start;\n}\n/** 用原生 DecompressionStream 解压 deflate-raw 数据 */\nasync function inflateRaw(compressed, name) {\n\ttry {\n\t\tconst stream = new ReadableStream({ start(controller) {\n\t\t\tcontroller.enqueue(compressed);\n\t\t\tcontroller.close();\n\t\t} }).pipeThrough(new DecompressionStream(\"deflate-raw\"));\n\t\treturn new Uint8Array(await new Response(stream).arrayBuffer());\n\t} catch (cause) {\n\t\tthrow new OfdParseError(\"truncated\", `条目 ${name} 的 deflate 数据无法解压`, { cause });\n\t}\n}\nfunction readU32(data, offset) {\n\treturn (data[offset + 3] << 24 | data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset]) >>> 0;\n}\n//#endregion\nexport { openOfdZip };\n\n//# sourceMappingURL=zip.js.map"],"mappings":"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"}
package/dist/style.d.ts CHANGED
@@ -4,6 +4,7 @@ import "./components/action/style.js";
4
4
  import "./components/dropdown/style.js";
5
5
  import "./components/input/style.js";
6
6
  import "./components/auto-complete/style.js";
7
+ import "./components/dialog/style.js";
7
8
  import "./components/checkbox/style.js";
8
9
  import "./components/radio/style.js";
9
10
  import "./components/table/style.js";
@@ -16,7 +17,6 @@ import "./components/condition-editor/style.js";
16
17
  import "./components/contextmenu/style.js";
17
18
  import "./components/date-picker/style.js";
18
19
  import "./components/date-range-picker/style.js";
19
- import "./components/dialog/style.js";
20
20
  import "./components/drawer/style.js";
21
21
  import "./components/dual-nav/style.js";
22
22
  import "./components/float-button/style.js";
package/dist/style.js CHANGED
@@ -9,6 +9,7 @@ import "./components/input/style.js";
9
9
  import "./components/tag/style.js";
10
10
  import "./components/auto-complete/style.js";
11
11
  import "./components/badge/style.js";
12
+ import "./components/dialog/style.js";
12
13
  import "./components/form-item/style.js";
13
14
  import "./components/grid/style.js";
14
15
  import "./components/form/style.js";
@@ -34,7 +35,6 @@ import "./components/contextmenu/style.js";
34
35
  import "./components/date-panel/style.js";
35
36
  import "./components/date-picker/style.js";
36
37
  import "./components/date-range-picker/style.js";
37
- import "./components/dialog/style.js";
38
38
  import "./components/drawer/style.js";
39
39
  import "./components/file-picker/style.js";
40
40
  import "./components/file-viewer/style.js";
@@ -38,6 +38,12 @@ export interface BatchEditProps extends TableProps {
38
38
  cols?: string | [string, string];
39
39
  /** 只读模式 */
40
40
  readonly?: boolean;
41
+ /**
42
+ * 表单交互模式
43
+ * @description `'panel'`:右侧面板(默认);`'dialog'`:编辑 / 新增 / 查看 / 添加子级时以弹框呈现表单
44
+ * @default 'panel'
45
+ */
46
+ formMode?: 'panel' | 'dialog';
41
47
  /**
42
48
  * 开启快速编辑
43
49
  * @description 开启后,编辑行时表单实时写回 `row.data`(经 `model` 中转),且不调用 `saveMethod`
@@ -2,7 +2,7 @@ import { ShallowRef } from "vue";
2
2
  import { DeconstructValue } from "@veltra/utils";
3
3
  //#region src/types/file-viewer.d.ts
4
4
  /** 预览器类别:xlsx 与 csv 归一为 sheet */
5
- export type FileViewerKind = 'image' | 'video' | 'pdf' | 'sheet' | 'docx' | 'text';
5
+ export type FileViewerKind = 'image' | 'video' | 'pdf' | 'sheet' | 'docx' | 'ofd' | 'text';
6
6
  /** 单个预览文件定义 */
7
7
  export interface FileViewerItem {
8
8
  /** 唯一 id;未提供时组件内部按索引生成 */
@@ -11,7 +11,7 @@ import { ScrollEmits, ScrollExposed, ScrollPosition, ScrollProps, _ScrollExposed
11
11
  import { WatermarkEmits, WatermarkExposed, WatermarkProps, _WatermarkExposed } from "./watermark.js";
12
12
  import { ProgressEmits, ProgressExposed, ProgressProps, _ProgressExposed } from "./progress.js";
13
13
  import { ProgressNodesEmits, ProgressNodesExposed, ProgressNodesProps, _ProgressNodesExposed } from "./progress-nodes.js";
14
- import { TipAlign, TipDirection, TipEmits, TipExposed, TipProps, _TipExposed } from "./tip.js";
14
+ import { TipAlign, TipDirection, TipEmits, TipExposed, TipProps, TipType, _TipExposed } from "./tip.js";
15
15
  import { PopConfirmEmits, PopConfirmExposed, PopConfirmProps, _PopConfirmExposed } from "./pop-confirm.js";
16
16
  import { TabItem, TabsEmits, TabsExposed, TabsHorizontalEmits, TabsHorizontalExposed, TabsHorizontalProps, TabsProps, TabsVerticalEmits, TabsVerticalExposed, TabsVerticalProps, _TabsExposed, _TabsHorizontalExposed, _TabsVerticalExposed } from "./tabs.js";
17
17
  import { BarType, TextEditorEmits, TextEditorExposed, TextEditorProps, _TextEditorExposed } from "./text-editor.js";
@@ -45,7 +45,7 @@ import { MultiTreeSelectEmits, MultiTreeSelectExposed, MultiTreeSelectProps, _Mu
45
45
  import { CodeEditorEmits, CodeEditorExposed, CodeEditorLang, CodeEditorProps, _CodeEditorExposed } from "./code-editor.js";
46
46
  import { TextEmits, TextExposed, TextProps, _TextExposed } from "./text.js";
47
47
  import { CheckboxGroupEmits, CheckboxGroupExposed, CheckboxGroupProps } from "./checkbox-group.js";
48
- import { TableEditorEmits, TableEditorExposed, TableEditorProps, _TableEditorExposed } from "./table-editor.js";
48
+ import { TableEditorColumn, TableEditorEmits, TableEditorExposed, TableEditorProps, _TableEditorExposed } from "./table-editor.js";
49
49
  import { NavEmits, NavExposed, NavItem, NavProps, _NavExposed } from "./nav.js";
50
50
  import { DualNavEmits, DualNavExposed, DualNavProps, DualNavRailVariant, DualNavRootItem, _DualNavExposed } from "./dual-nav.js";
51
51
  import { GroupNavEmits, GroupNavGroup, GroupNavProps } from "./group-nav.js";
@@ -82,4 +82,4 @@ import { CollapseEmits, CollapseItemEmits, CollapseItemProps, CollapseModelValue
82
82
  import { SegmentEmits, SegmentExposed, SegmentItem, SegmentProps, _SegmentExposed } from "./segment.js";
83
83
  import { ImageCropperChangePayload, ImageCropperCropTransform, ImageCropperEmits, ImageCropperExposed, ImageCropperProps, ImageCropperResult, ImageCropperResultOptions, ImageCropperSelection, _ImageCropperExposed } from "./image-cropper.js";
84
84
  export type * from "@veltra/utils";
85
- export { ActionEmits, ActionExposed, ActionGroupExposed, ActionGroupProps, ActionProps, AnimationEmits, AnimationExposed, AnimationProps, AutoCompleteEmits, AutoCompleteExposed, AutoCompleteProps, BadgeEmits, BadgeExposed, BadgeProps, BarType, BatchEditColumn, BatchEditEmits, BatchEditExposed, BatchEditFeature, BatchEditFormStatus, BatchEditProps, BatchEditSlots, BatchEditStates, BreadcrumbEmits, BreadcrumbExposed, BreadcrumbItem, BreadcrumbProps, BreadcrumbSlotScope, BreakCols, Breakpoint, ButtonEmits, ButtonExposed, ButtonProps, ButtonType, CalendarDay, CalendarEmits, CalendarExposed, CalendarMonth, CalendarProps, CalendarYear, CardActionProps, CardContentProps, CardCoverProps, CardEmits, CardExposed, CardProps, CascadeEmits, CascadeExposed, CascadeNode, CascadeProps, CheckTagEmits, CheckTagExposed, CheckTagProps, CheckboxButtonEmits, CheckboxButtonProps, CheckboxEmits, CheckboxExposed, CheckboxGroupEmits, CheckboxGroupExposed, CheckboxGroupProps, CheckboxProps, CodeEditorEmits, CodeEditorExposed, CodeEditorLang, CodeEditorProps, CollapseEmits, CollapseItemEmits, CollapseItemProps, CollapseModelValue, CollapseProps, CollapseValue, ConditionConnector, ConditionEditorEmits, ConditionEditorExposed, ConditionEditorProps, ConditionExpression, ConditionField, ConditionGroup, ConditionLeaf, ConditionNode, ConditionValue, ContextmenuEmits, ContextmenuExposed, ContextmenuItem, ContextmenuProps, CssTransitionEmits, CssTransitionExposed, CssTransitionProps, DatePanelEmits, DatePanelProps, DatePickerDataType, DatePickerEmits, DatePickerExposed, DatePickerProps, DateRangePickerDataType, DateRangePickerEmits, DateRangePickerExposed, DateRangePickerProps, DateRangeValue, DialogEmits, DialogExposed, DialogProps, DialogTransition, DrawerDirection, DrawerEmits, DrawerExposed, DrawerMode, DrawerProps, DropdownEmits, DropdownExposed, DropdownProps, DualNavEmits, DualNavExposed, DualNavProps, DualNavRailVariant, DualNavRootItem, EmptyEmits, EmptyExposed, EmptyProps, ExpressionEditorEmits, ExpressionEditorExposed, ExpressionEditorProps, ExpressionSelectableLevels, FileViewerEmits, FileViewerExposed, FileViewerItem, FileViewerKind, FileViewerProps, FloatButtonEmits, FloatButtonExposed, FloatButtonItem, FloatButtonProps, FormEmits, FormExposed, FormItemEmits, FormItemExposed, FormItemProps, FormProps, GanttChartEmits, GanttChartExposed, GanttChartProps, GridEmits, GridExposed, GridInputEmits, GridInputExposed, GridInputProps, GridItemProps, GridProps, GroupInputEmits, GroupInputExposed, GroupInputProps, GroupNavEmits, GroupNavGroup, GroupNavProps, IconEmits, IconExposed, IconProps, ImageCropperChangePayload, ImageCropperCropTransform, ImageCropperEmits, ImageCropperExposed, ImageCropperProps, ImageCropperResult, ImageCropperResultOptions, ImageCropperSelection, InputEmits, InputExposed, InputProps, LayoutEmits, LayoutExposed, LayoutProps, ListEmits, ListExposed, ListProps, LoadingEmits, LoadingExposed, LoadingProps, LoadingType, Message, MessageConfirm, MessageConfirmAction, MessageConfirmEmits, MessageConfirmExposed, MessageConfirmInstance, MessageConfirmOptions, MessageConfirmProps, MessageEmits, MessageExposed, MessageInstance, MessageOptions, MessageProps, MessageType, MultiAutoCompleteEmits, MultiAutoCompleteExposed, MultiAutoCompleteProps, MultiSelectEmits, MultiSelectExposed, MultiSelectProps, MultiTreeSelectEmits, MultiTreeSelectExposed, MultiTreeSelectProps, NavEmits, NavExposed, NavItem, NavProps, NodeRenderExposed, NodeRenderProps, Notification, NotificationEmits, NotificationExposed, NotificationInstance, NotificationOptions, NotificationPosition, NotificationProps, NumberEmits, NumberExposed, NumberInputEmits, NumberInputExposed, NumberInputProps, NumberProps, NumberRangeInputEmits, NumberRangeInputExposed, NumberRangeInputProps, NumberRangeTuple, PaginatorEmits, PaginatorExposed, PaginatorProps, PaletteColorType, PaletteEmits, PaletteExposed, PaletteHSV, PaletteProps, PaletteRGB, PanelItem, PanelType, PasswordInputEmits, PasswordInputExposed, PasswordInputProps, PopConfirmEmits, PopConfirmExposed, PopConfirmProps, PopEmits, PopExposed, PopProps, ProgressEmits, ProgressExposed, ProgressNodesEmits, ProgressNodesExposed, ProgressNodesProps, ProgressProps, QuickBatchEditEmits, QuickBatchEditExposed, QuickBatchEditProps, RadioEmits, RadioExposed, RadioGroupEmits, RadioGroupExposed, RadioGroupProps, RadioProps, RichTextEditorEmits, RichTextEditorExposed, RichTextEditorProps, RichTextFormat, ScrollEmits, ScrollExposed, ScrollPosition, ScrollProps, SegmentEmits, SegmentExposed, SegmentItem, SegmentProps, SelectEmits, SelectExposed, SelectProps, SliderEmits, SliderExposed, SliderProps, StepsEmits, StepsExposed, StepsProps, StepsSlotScope, SwitchEmits, SwitchExposed, SwitchProps, TabItem, TableColumn, TableColumnAlign, TableColumnNode, TableColumnRenderContext, TableColumnSlotsScope, TableColumnStyle, TableEditorEmits, TableEditorExposed, TableEditorProps, TableEmits, TableExposed, TableProps, TableRow, TableRowSlotsScope, TableSummaryContext, TabsEmits, TabsExposed, TabsHorizontalEmits, TabsHorizontalExposed, TabsHorizontalProps, TabsProps, TabsVerticalEmits, TabsVerticalExposed, TabsVerticalProps, TagEmits, TagExposed, TagProps, TextEditorEmits, TextEditorExposed, TextEditorProps, TextEmits, TextExposed, TextProps, TextareaEmits, TextareaExposed, TextareaProps, ThemeExposed, ThemeProps, TipAlign, TipDirection, TipEmits, TipExposed, TipProps, ToolbarItem, TreeEmit, TreeExposed, TreeNode, TreeNodeProps, TreeProps, TreeSelectEmits, TreeSelectExposed, TreeSelectProps, UploaderEmits, UploaderExposed, UploaderProps, VariableItem, WatermarkEmits, WatermarkExposed, WatermarkProps, _ActionExposed, _ActionGroupExposed, _AnimationExposed, _AutoCompleteExposed, _BadgeExposed, _BatchEditExposed, _BreadcrumbExposed, _ButtonExposed, _CalendarExposed, _CardExposed, _CascadeExposed, _CheckTagExposed, _CodeEditorExposed, _ConditionEditorExposed, _ContextmenuExposed, _CssTransitionExposed, _DatePickerExposed, _DateRangePickerExposed, _DialogExposed, _DrawerExposed, _DropdownExposed, _DualNavExposed, _EmptyExposed, _ExpressionEditorExposed, _FileViewerExposed, _FloatButtonExposed, _FormExposed, _GanttChartExposed, _GridExposed, _GridInputExposed, _GroupInputExposed, _ImageCropperExposed, _InputExposed, _LayoutExposed, _ListExposed, _LoadingExposed, _MessageConfirmExposed, _MessageExposed, _MultiAutoCompleteExposed, _MultiSelectExposed, _MultiTreeSelectExposed, _NavExposed, _NotificationExposed, _PaginatorExposed, _PaletteExposed, _PasswordInputExposed, _PopConfirmExposed, _PopExposed, _ProgressExposed, _ProgressNodesExposed, _QuickBatchEditExposed, _RadioExposed, _RadioGroupExposed, _RichTextEditorExposed, _ScrollExposed, _SegmentExposed, _SelectExposed, _SliderExposed, _StepsExposed, _SwitchExposed, _TableEditorExposed, _TableExposed, _TabsExposed, _TabsHorizontalExposed, _TabsVerticalExposed, _TextEditorExposed, _TextExposed, _TextareaExposed, _ThemeExposed, _TipExposed, _TreeExposed, _TreeSelectExposed, _UploaderExposed, _WatermarkExposed };
85
+ export { ActionEmits, ActionExposed, ActionGroupExposed, ActionGroupProps, ActionProps, AnimationEmits, AnimationExposed, AnimationProps, AutoCompleteEmits, AutoCompleteExposed, AutoCompleteProps, BadgeEmits, BadgeExposed, BadgeProps, BarType, BatchEditColumn, BatchEditEmits, BatchEditExposed, BatchEditFeature, BatchEditFormStatus, BatchEditProps, BatchEditSlots, BatchEditStates, BreadcrumbEmits, BreadcrumbExposed, BreadcrumbItem, BreadcrumbProps, BreadcrumbSlotScope, BreakCols, Breakpoint, ButtonEmits, ButtonExposed, ButtonProps, ButtonType, CalendarDay, CalendarEmits, CalendarExposed, CalendarMonth, CalendarProps, CalendarYear, CardActionProps, CardContentProps, CardCoverProps, CardEmits, CardExposed, CardProps, CascadeEmits, CascadeExposed, CascadeNode, CascadeProps, CheckTagEmits, CheckTagExposed, CheckTagProps, CheckboxButtonEmits, CheckboxButtonProps, CheckboxEmits, CheckboxExposed, CheckboxGroupEmits, CheckboxGroupExposed, CheckboxGroupProps, CheckboxProps, CodeEditorEmits, CodeEditorExposed, CodeEditorLang, CodeEditorProps, CollapseEmits, CollapseItemEmits, CollapseItemProps, CollapseModelValue, CollapseProps, CollapseValue, ConditionConnector, ConditionEditorEmits, ConditionEditorExposed, ConditionEditorProps, ConditionExpression, ConditionField, ConditionGroup, ConditionLeaf, ConditionNode, ConditionValue, ContextmenuEmits, ContextmenuExposed, ContextmenuItem, ContextmenuProps, CssTransitionEmits, CssTransitionExposed, CssTransitionProps, DatePanelEmits, DatePanelProps, DatePickerDataType, DatePickerEmits, DatePickerExposed, DatePickerProps, DateRangePickerDataType, DateRangePickerEmits, DateRangePickerExposed, DateRangePickerProps, DateRangeValue, DialogEmits, DialogExposed, DialogProps, DialogTransition, DrawerDirection, DrawerEmits, DrawerExposed, DrawerMode, DrawerProps, DropdownEmits, DropdownExposed, DropdownProps, DualNavEmits, DualNavExposed, DualNavProps, DualNavRailVariant, DualNavRootItem, EmptyEmits, EmptyExposed, EmptyProps, ExpressionEditorEmits, ExpressionEditorExposed, ExpressionEditorProps, ExpressionSelectableLevels, FileViewerEmits, FileViewerExposed, FileViewerItem, FileViewerKind, FileViewerProps, FloatButtonEmits, FloatButtonExposed, FloatButtonItem, FloatButtonProps, FormEmits, FormExposed, FormItemEmits, FormItemExposed, FormItemProps, FormProps, GanttChartEmits, GanttChartExposed, GanttChartProps, GridEmits, GridExposed, GridInputEmits, GridInputExposed, GridInputProps, GridItemProps, GridProps, GroupInputEmits, GroupInputExposed, GroupInputProps, GroupNavEmits, GroupNavGroup, GroupNavProps, IconEmits, IconExposed, IconProps, ImageCropperChangePayload, ImageCropperCropTransform, ImageCropperEmits, ImageCropperExposed, ImageCropperProps, ImageCropperResult, ImageCropperResultOptions, ImageCropperSelection, InputEmits, InputExposed, InputProps, LayoutEmits, LayoutExposed, LayoutProps, ListEmits, ListExposed, ListProps, LoadingEmits, LoadingExposed, LoadingProps, LoadingType, Message, MessageConfirm, MessageConfirmAction, MessageConfirmEmits, MessageConfirmExposed, MessageConfirmInstance, MessageConfirmOptions, MessageConfirmProps, MessageEmits, MessageExposed, MessageInstance, MessageOptions, MessageProps, MessageType, MultiAutoCompleteEmits, MultiAutoCompleteExposed, MultiAutoCompleteProps, MultiSelectEmits, MultiSelectExposed, MultiSelectProps, MultiTreeSelectEmits, MultiTreeSelectExposed, MultiTreeSelectProps, NavEmits, NavExposed, NavItem, NavProps, NodeRenderExposed, NodeRenderProps, Notification, NotificationEmits, NotificationExposed, NotificationInstance, NotificationOptions, NotificationPosition, NotificationProps, NumberEmits, NumberExposed, NumberInputEmits, NumberInputExposed, NumberInputProps, NumberProps, NumberRangeInputEmits, NumberRangeInputExposed, NumberRangeInputProps, NumberRangeTuple, PaginatorEmits, PaginatorExposed, PaginatorProps, PaletteColorType, PaletteEmits, PaletteExposed, PaletteHSV, PaletteProps, PaletteRGB, PanelItem, PanelType, PasswordInputEmits, PasswordInputExposed, PasswordInputProps, PopConfirmEmits, PopConfirmExposed, PopConfirmProps, PopEmits, PopExposed, PopProps, ProgressEmits, ProgressExposed, ProgressNodesEmits, ProgressNodesExposed, ProgressNodesProps, ProgressProps, QuickBatchEditEmits, QuickBatchEditExposed, QuickBatchEditProps, RadioEmits, RadioExposed, RadioGroupEmits, RadioGroupExposed, RadioGroupProps, RadioProps, RichTextEditorEmits, RichTextEditorExposed, RichTextEditorProps, RichTextFormat, ScrollEmits, ScrollExposed, ScrollPosition, ScrollProps, SegmentEmits, SegmentExposed, SegmentItem, SegmentProps, SelectEmits, SelectExposed, SelectProps, SliderEmits, SliderExposed, SliderProps, StepsEmits, StepsExposed, StepsProps, StepsSlotScope, SwitchEmits, SwitchExposed, SwitchProps, TabItem, TableColumn, TableColumnAlign, TableColumnNode, TableColumnRenderContext, TableColumnSlotsScope, TableColumnStyle, TableEditorColumn, TableEditorEmits, TableEditorExposed, TableEditorProps, TableEmits, TableExposed, TableProps, TableRow, TableRowSlotsScope, TableSummaryContext, TabsEmits, TabsExposed, TabsHorizontalEmits, TabsHorizontalExposed, TabsHorizontalProps, TabsProps, TabsVerticalEmits, TabsVerticalExposed, TabsVerticalProps, TagEmits, TagExposed, TagProps, TextEditorEmits, TextEditorExposed, TextEditorProps, TextEmits, TextExposed, TextProps, TextareaEmits, TextareaExposed, TextareaProps, ThemeExposed, ThemeProps, TipAlign, TipDirection, TipEmits, TipExposed, TipProps, TipType, ToolbarItem, TreeEmit, TreeExposed, TreeNode, TreeNodeProps, TreeProps, TreeSelectEmits, TreeSelectExposed, TreeSelectProps, UploaderEmits, UploaderExposed, UploaderProps, VariableItem, WatermarkEmits, WatermarkExposed, WatermarkProps, _ActionExposed, _ActionGroupExposed, _AnimationExposed, _AutoCompleteExposed, _BadgeExposed, _BatchEditExposed, _BreadcrumbExposed, _ButtonExposed, _CalendarExposed, _CardExposed, _CascadeExposed, _CheckTagExposed, _CodeEditorExposed, _ConditionEditorExposed, _ContextmenuExposed, _CssTransitionExposed, _DatePickerExposed, _DateRangePickerExposed, _DialogExposed, _DrawerExposed, _DropdownExposed, _DualNavExposed, _EmptyExposed, _ExpressionEditorExposed, _FileViewerExposed, _FloatButtonExposed, _FormExposed, _GanttChartExposed, _GridExposed, _GridInputExposed, _GroupInputExposed, _ImageCropperExposed, _InputExposed, _LayoutExposed, _ListExposed, _LoadingExposed, _MessageConfirmExposed, _MessageExposed, _MultiAutoCompleteExposed, _MultiSelectExposed, _MultiTreeSelectExposed, _NavExposed, _NotificationExposed, _PaginatorExposed, _PaletteExposed, _PasswordInputExposed, _PopConfirmExposed, _PopExposed, _ProgressExposed, _ProgressNodesExposed, _QuickBatchEditExposed, _RadioExposed, _RadioGroupExposed, _RichTextEditorExposed, _ScrollExposed, _SegmentExposed, _SelectExposed, _SliderExposed, _StepsExposed, _SwitchExposed, _TableEditorExposed, _TableExposed, _TabsExposed, _TabsHorizontalExposed, _TabsVerticalExposed, _TextEditorExposed, _TextExposed, _TextareaExposed, _ThemeExposed, _TipExposed, _TreeExposed, _TreeSelectExposed, _UploaderExposed, _WatermarkExposed };
@@ -1,17 +1,38 @@
1
- import { TableProps } from "./table.js";
2
- import { DeconstructValue } from "@veltra/utils";
1
+ import { TableColumn, TableProps } from "./table.js";
2
+ import { DeconstructValue, ValidateRule } from "@veltra/utils";
3
3
  //#region src/types/table-editor.d.ts
4
- /** 表格型编辑器组件属性 */
5
- export interface TableEditorProps extends Omit<TableProps, 'data'> {
4
+ /** 表格编辑器列:在 TableColumn 基础上扩展按列校验 */
5
+ export interface TableEditorColumn extends TableColumn {
6
+ /** 列校验规则:配置后该列控件的 change 事件触发单元格校验,`required` 非空时表头列名前渲染红星 */
7
+ rules?: ValidateRule;
8
+ }
9
+ /**
10
+ * 表格型编辑器组件属性
11
+ *
12
+ * 单元格常驻渲染:声明了 `#column:key` 插槽的列,输入控件常驻挂载;
13
+ * 未声明编辑插槽的列渲染字段原始值。
14
+ */
15
+ export interface TableEditorProps extends Omit<TableProps, 'data' | 'columns'> {
6
16
  /** 表格数据 */
7
- modelValue?: any[];
17
+ modelValue?: Record<string, any>[];
18
+ /** 表格列 */
19
+ columns?: TableEditorColumn[];
20
+ /**
21
+ * 只读模式
22
+ * @default false
23
+ * @description 只读下输入控件经插槽 model 收到 readonly: true(值不可修改),操作列与空态「添加」按钮不渲染
24
+ */
25
+ readonly?: boolean;
8
26
  }
9
27
  /** 表格型编辑器组件定义的事件 */
10
28
  export interface TableEditorEmits {
11
- (e: 'update:modelValue', value: any[]): void;
29
+ (e: 'update:modelValue', value: Record<string, any>[]): void;
12
30
  }
13
31
  /** 表格型编辑器组件暴露的属性和方法(组件内部使用) */
14
- export interface _TableEditorExposed {}
32
+ export interface _TableEditorExposed {
33
+ /** 校验全表配置了 rules 的列,全部通过 resolve true,任一失败 resolve false */
34
+ validate(): Promise<boolean>;
35
+ }
15
36
  /** 表格型编辑器组件暴露的属性和方法(组件外部使用, 引用的值会被自动解构) */
16
37
  export type TableEditorExposed = DeconstructValue<_TableEditorExposed>;
17
38
  //#endregion
@@ -1,12 +1,16 @@
1
1
  import { CSSProperties } from "vue";
2
- import { DeconstructValue } from "@veltra/utils";
2
+ import { ColorType, DeconstructValue } from "@veltra/utils";
3
3
  //#region src/types/tip.d.ts
4
4
  export type TipDirection = 'top' | 'bottom' | 'left' | 'right';
5
5
  export type TipAlign = 'center' | 'start' | 'end';
6
+ /** tip类型 */
7
+ export type TipType = ColorType;
6
8
  /** tip提示组件组件属性 */
7
9
  export interface TipProps {
8
10
  /** 控制显影 */
9
11
  visible?: boolean;
12
+ /** tip类型 */
13
+ type?: TipType;
10
14
  /**提示内容 */
11
15
  content?: string;
12
16
  /** 自定义tip样式 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/desktop",
3
- "version": "1.7.13",
3
+ "version": "1.7.15",
4
4
  "homepage": "https://github.com/cabinet-fe/ultra-ui#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/cabinet-fe/ultra-ui/issues"
@@ -75,17 +75,18 @@
75
75
  "@codemirror/search": "6.7.1",
76
76
  "@codemirror/state": "6.7.1",
77
77
  "@codemirror/theme-one-dark": "6.1.3",
78
- "@codemirror/view": "6.43.9"
78
+ "@codemirror/view": "6.43.9",
79
+ "@veltra/ofd-core": "1.0.1"
79
80
  },
80
81
  "peerDependencies": {
81
82
  "@cat-kit/core": ">=1.2.1",
82
83
  "@cat-kit/fe": ">=1.2.1",
83
- "@veltra/compositions": "^1.7.13",
84
- "@veltra/directives": "^1.7.13",
84
+ "@veltra/compositions": "^1.7.14",
85
+ "@veltra/directives": "^1.7.14",
85
86
  "@veltra/icons": "^1.5.0",
86
- "@veltra/sheet-core": "^2.5.6",
87
- "@veltra/styles": "^1.7.13",
88
- "@veltra/utils": "^1.7.13",
87
+ "@veltra/sheet-core": "^2.5.7",
88
+ "@veltra/styles": "^1.7.14",
89
+ "@veltra/utils": "^1.7.14",
89
90
  "vue": ">=3.5.42"
90
91
  },
91
92
  "peerDependenciesMeta": {