Quellcode durchsuchen

fix: new wisdom-pptxtojson

Lee vor 4 Wochen
Ursprung
Commit
5645afb37a

+ 1 - 0
components.d.ts

@@ -23,6 +23,7 @@ declare module 'vue' {
     PPT: typeof import('./src/components/view_file/vendors/pptx/PPT.vue')['default']
     PPT2: typeof import('./src/components/view_file/vendors/pptx/PPT2.vue')['default']
     PPT3: typeof import('./src/components/view_file/vendors/pptx/PPT3.vue')['default']
+    PPTOld: typeof import('./src/components/view_file/vendors/pptx/PPT-old.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     Table: typeof import('./src/components/view_file/vendors/xlsx/Table.vue')['default']

+ 1 - 0
package.json

@@ -18,6 +18,7 @@
         "tinycolor2": "1.6.0",
         "vue": "^3.5.13",
         "vue-router": "4",
+        "pptxtojson": "^1.5.0",
         "wisdom-pptxtojson": "^1.0.0",
         "x-data-spreadsheet": "^1.1.9"
     },

+ 12 - 0
pnpm-lock.yaml

@@ -26,6 +26,9 @@ importers:
       pdfjs-dist:
         specifier: ^5.1.91
         version: 5.1.91
+      pptxtojson:
+        specifier: ^1.5.0
+        version: 1.9.0
       tinycolor2:
         specifier: 1.6.0
         version: 1.6.0
@@ -1108,6 +1111,9 @@ packages:
     resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
     engines: {node: ^10 || ^12 || >=14}
 
+  pptxtojson@1.9.0:
+    resolution: {integrity: sha512-SUj9axuZRaBEN/No2yjsFW0noFxywAdLoOFZRaf/ftduJX6Js7R4ONqbNi1f4tE+N3Lbecznw8XEVznOUW91Hg==}
+
   process-nextick-args@2.0.1:
     resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
 
@@ -2397,6 +2403,12 @@ snapshots:
       picocolors: 1.1.1
       source-map-js: 1.2.1
 
+  pptxtojson@1.9.0:
+    dependencies:
+      jszip: 3.10.1
+      tinycolor2: 1.6.0
+      txml: 5.1.1
+
   process-nextick-args@2.0.1: {}
 
   prr@1.0.1:

+ 1856 - 248
src/components/view_file/vendors/pptx/PPT.vue

@@ -1,309 +1,1917 @@
 <!--
  * @Author: LiZhiWei
- * @Date: 2025-04-10 14:38:27
+ * @Date: 2025-12-26 14:41:26
  * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-22 16:58:24
- * @Description:
+ * @LastEditTime: 2025-12-26 17:39:45
+ * @Description: 
 -->
 <template>
-  <div id="pptx-container" ref="pptxContainer" class="pptx-container"></div>
+  <div ref="rootRef" class="pptx-preview">
+    <div v-if="!slides.length" class="pptx-empty">暂无可渲染的幻灯片</div>
+    <div v-else class="pptx-slides">
+      <div
+        v-for="(slide, slideIndex) in slides"
+        :key="slideIndex"
+        class="pptx-slide-shell"
+        :style="getSlideShellStyle()"
+      >
+        <div
+          class="pptx-slide"
+          :style="getSlideStyle(slide)"
+        >
+          <div
+            v-for="(el, elementIndex) in slide.elements"
+            :key="getElementKey(el, elementIndex)"
+            class="pptx-element"
+            :style="getElementStyle(el, elementIndex)"
+          >
+            <template v-if="isImageElement(el)">
+              <div class="pptx-img-wrap" :style="getImageWrapStyle(el)">
+                <img
+                  class="pptx-img"
+                  :src="getMediaSrc(el)"
+                  :style="getImageStyle(el)"
+                  alt=""
+                  draggable="false"
+                />
+              </div>
+            </template>
+
+            <template v-else-if="isVideoElement(el)">
+              <video class="pptx-media" :src="getMediaSrc(el)" controls preload="metadata" />
+            </template>
+
+            <template v-else-if="isAudioElement(el)">
+              <audio class="pptx-media" :src="getMediaSrc(el)" controls preload="metadata" />
+            </template>
+
+            <template v-else-if="isMathElement(el)">
+              <img class="pptx-img" :src="getMediaSrc(el)" alt="" draggable="false" />
+            </template>
+
+            <template v-else-if="isChartElement(el)">
+              <svg
+                class="pptx-chart"
+                :viewBox="`0 0 ${getNumber(el.width)} ${getNumber(el.height)}`"
+                preserveAspectRatio="none"
+              >
+                <template v-if="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).kind === 'bar'">
+                  <rect
+                    v-for="(b, i) in getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).bars"
+                    :key="i"
+                    :x="b.x"
+                    :y="b.y"
+                    :width="b.w"
+                    :height="b.h"
+                    :fill="b.fill"
+                    :fill-opacity="b.opacity"
+                  />
+                </template>
+
+                <template v-else-if="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).kind === 'line'">
+                  <path
+                    v-for="(p, i) in getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).paths"
+                    :key="i"
+                    :d="p.d"
+                    fill="none"
+                    :stroke="p.stroke"
+                    :stroke-width="p.strokeWidth"
+                    stroke-linejoin="round"
+                    stroke-linecap="round"
+                  />
+                  <circle
+                    v-for="(pt, i) in getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).points"
+                    :key="i"
+                    :cx="pt.cx"
+                    :cy="pt.cy"
+                    :r="pt.r"
+                    :fill="pt.fill"
+                    :fill-opacity="pt.opacity"
+                  />
+                </template>
+
+                <template v-else-if="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).kind === 'pie'">
+                  <path
+                    v-for="(s, i) in getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).slices"
+                    :key="i"
+                    :d="s.d"
+                    :fill="s.fill"
+                    :fill-opacity="s.opacity"
+                  />
+                  <circle
+                    v-if="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).holeR"
+                    :cx="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).cx"
+                    :cy="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).cy"
+                    :r="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).holeR"
+                    fill="#fff"
+                  />
+                </template>
+
+                <template v-else-if="getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).kind === 'scatter'">
+                  <circle
+                    v-for="(pt, i) in getChartModel(el, slideIndex, getElementCacheId(el, elementIndex)).points"
+                    :key="i"
+                    :cx="pt.cx"
+                    :cy="pt.cy"
+                    :r="pt.r"
+                    :fill="pt.fill"
+                    :fill-opacity="pt.opacity"
+                  />
+                </template>
+              </svg>
+            </template>
+
+            <template v-else-if="isGroupElement(el) || isDiagramElement(el)">
+              <PptxGroup
+                :el="el"
+                :slide-index="slideIndex"
+                :cache-id="getElementCacheId(el, elementIndex)"
+                :abs-left="getNumber(el.left)"
+                :abs-top="getNumber(el.top)"
+              />
+            </template>
+
+            <template v-else-if="isTableElement(el)">
+              <div class="pptx-table-wrap">
+                <table class="pptx-table">
+                  <colgroup v-if="getTableModel(el, slideIndex, getElementCacheId(el, elementIndex)).colWidths.length">
+                    <col
+                      v-for="(w, i) in getTableModel(el, slideIndex, getElementCacheId(el, elementIndex)).colWidths"
+                      :key="i"
+                      :style="{ width: w ? `${w}px` : undefined }"
+                    />
+                  </colgroup>
+                  <tbody>
+                    <tr
+                      v-for="(row, ri) in getTableModel(el, slideIndex, getElementCacheId(el, elementIndex)).rows"
+                      :key="ri"
+                      :style="getTableRowStyle(el, slideIndex, getElementCacheId(el, elementIndex), ri)"
+                    >
+                      <template v-for="(cell, ci) in row" :key="`${ri}-${ci}`">
+                        <td
+                          v-if="!cell.skip"
+                          :colspan="cell.colspan"
+                          :rowspan="cell.rowspan"
+                          :style="cell.style"
+                        >
+                          <div class="pptx-table-html" v-html="sanitizeHtml(cell.html)" />
+                        </td>
+                      </template>
+                    </tr>
+                  </tbody>
+                </table>
+              </div>
+            </template>
+
+            <template v-else-if="isShapeElement(el)">
+              <svg
+                class="pptx-shape-svg"
+                :viewBox="`0 0 ${getNumber(el.width)} ${getNumber(el.height)}`"
+                preserveAspectRatio="none"
+              >
+                <defs v-if="hasShapeDefs(el, slideIndex, getElementCacheId(el, elementIndex))">
+                  <linearGradient
+                    v-if="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))?.kind === 'linear'"
+                    :id="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.id"
+                    :x1="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.x1"
+                    :y1="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.y1"
+                    :x2="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.x2"
+                    :y2="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.y2"
+                  >
+                    <stop
+                      v-for="(s, i) in getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.stops"
+                      :key="i"
+                      :offset="s.offset"
+                      :stop-color="s.color"
+                      :stop-opacity="s.opacity"
+                    />
+                  </linearGradient>
+
+                  <radialGradient
+                    v-else-if="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))?.kind === 'radial'"
+                    :id="getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.id"
+                    cx="50%"
+                    cy="50%"
+                    r="50%"
+                  >
+                    <stop
+                      v-for="(s, i) in getShapeGradient(el, slideIndex, getElementCacheId(el, elementIndex))!.stops"
+                      :key="i"
+                      :offset="s.offset"
+                      :stop-color="s.color"
+                      :stop-opacity="s.opacity"
+                    />
+                  </radialGradient>
+
+                  <pattern
+                    v-if="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))"
+                    :id="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.id"
+                    patternUnits="userSpaceOnUse"
+                    :width="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.width"
+                    :height="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.height"
+                  >
+                    <rect
+                      x="0"
+                      y="0"
+                      :width="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.width"
+                      :height="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.height"
+                      :fill="getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.background"
+                    />
+                    <template
+                      v-for="(shape, i) in getShapePattern(el, slideIndex, getElementCacheId(el, elementIndex))!.shapes"
+                      :key="i"
+                    >
+                      <circle
+                        v-if="shape.kind === 'circle'"
+                        :cx="shape.cx"
+                        :cy="shape.cy"
+                        :r="shape.r"
+                        :fill="shape.fill"
+                      />
+                      <polygon
+                        v-else-if="shape.kind === 'polygon'"
+                        :points="shape.points"
+                        :fill="shape.fill"
+                      />
+                      <rect
+                        v-else-if="shape.kind === 'rect'"
+                        :x="shape.x"
+                        :y="shape.y"
+                        :width="shape.width"
+                        :height="shape.height"
+                        :fill="shape.fill"
+                        :transform="shape.transform"
+                      />
+                    </template>
+                  </pattern>
+
+                  <pattern
+                    v-if="getShapeImagePaint(el, slideIndex, getElementCacheId(el, elementIndex))"
+                    :id="getShapeImagePaint(el, slideIndex, getElementCacheId(el, elementIndex))!.id"
+                    patternUnits="objectBoundingBox"
+                    width="1"
+                    height="1"
+                  >
+                    <image
+                      x="0"
+                      y="0"
+                      width="1"
+                      height="1"
+                      preserveAspectRatio="none"
+                      :href="getShapeImagePaint(el, slideIndex, getElementCacheId(el, elementIndex))!.href"
+                    />
+                  </pattern>
+                </defs>
+
+                <path
+                  :d="getShapePath(el)"
+                  :fill="getShapeFill(el, slideIndex, getElementCacheId(el, elementIndex))"
+                  :stroke="getShapeStroke(el)"
+                  :stroke-width="getShapeStrokeWidth(el)"
+                  :stroke-dasharray="getShapeDasharray(el)"
+                />
+              </svg>
+
+              <div
+                v-if="typeof el.content === 'string' && el.content.trim()"
+                class="pptx-html"
+                :style="getHtmlBoxStyle(el)"
+              >
+                <div
+                  class="pptx-html-inner"
+                  :style="getHtmlInnerStyle(el)"
+                  v-html="sanitizeHtml(el.content)"
+                />
+              </div>
+            </template>
+
+            <template v-else>
+              <div
+                v-if="typeof el.content === 'string' && el.content.trim()"
+                class="pptx-html"
+                :style="getHtmlBoxStyle(el)"
+              >
+                <div
+                  class="pptx-html-inner"
+                  :style="getHtmlInnerStyle(el)"
+                  v-html="sanitizeHtml(el.content)"
+                />
+              </div>
+            </template>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
 </template>
 
-<script setup>
-import { ref, watch, onMounted } from "vue"
-import { createImageElement } from "./elements/image"
-import { createVideoElement } from "./elements/video"
-import { createTextElement } from "./elements/text"
-import { createAudioElement } from "./elements/audio"
-import { createShapeElement } from "./elements/shape"
-import { createTableElement } from "./elements/table"
-import { createChartElement } from "./elements/chart"
-import { createDiagramElement } from "./elements/smartArt"
-import { createMathElement } from "./elements/math"
-const props = defineProps({
-  pptxJson: Object,
+<script setup lang="ts">
+import { computed, defineComponent, h, onBeforeUnmount, onMounted, ref } from "vue"
+import type { CSSProperties } from "vue"
+
+type PptxSize = {
+  width: number
+  height: number
+}
+
+type PptxFill = {
+  type?: string
+  value?: any
+}
+
+type PptxElement = {
+  type?: string
+  left?: number
+  top?: number
+  width?: number
+  height?: number
+  rotate?: number
+  order?: number
+  opacity?: number
+  isFlipH?: boolean
+  isFlipV?: boolean
+  vAlign?: "up" | "mid" | "down" | string
+  content?: string
+  fill?: PptxFill | string
+  path?: string
+  borderColor?: string
+  borderWidth?: number
+  borderStrokeDasharray?: string
+  __source?: "layout" | "slide"
+  [key: string]: any
+}
+
+type PptxSlide = {
+  fill?: PptxFill
+  elements?: PptxElement[]
+  layoutElements?: PptxElement[]
+  [key: string]: any
+}
+
+type PptxJson = {
+  size?: PptxSize
+  slides?: PptxSlide[]
+  [key: string]: any
+}
+
+const props = defineProps<{ pptxJson: PptxJson }>()
+
+const rootRef = ref<HTMLDivElement | null>(null)
+const containerWidth = ref(0)
+
+let resizeObserver: ResizeObserver | null = null
+
+const size = computed<PptxSize>(() => {
+  const w = (props.pptxJson?.size?.width ?? 960) as number
+  const h = (props.pptxJson?.size?.height ?? 540) as number
+  return {
+    width: Number.isFinite(w) ? w : 960,
+    height: Number.isFinite(h) ? h : 540,
+  }
 })
 
-const pptxContainer = ref(null)
+const scale = computed(() => {
+  const w = containerWidth.value
+  if (!w) return 1
+  const raw = w / size.value.width
+  return Math.min(1, Math.max(0.1, raw))
+})
 
-// 渲染幻灯片
-const renderSlides = () => {
-  if (!pptxContainer.value || !props.pptxJson) return
+const slides = computed(() => {
+  const rawSlides = Array.isArray(props.pptxJson?.slides) ? props.pptxJson.slides : []
+  return rawSlides.map((slide) => {
+    const layoutElements = (Array.isArray(slide.layoutElements) ? slide.layoutElements : []).map((el) => ({
+      ...(el as any),
+      __source: "layout" as const,
+    }))
 
-  pptxContainer.value.innerHTML = ""
-  const { size, slides } = props.pptxJson
+    const slideElements = (Array.isArray(slide.elements) ? slide.elements : []).map((el) => ({
+      ...(el as any),
+      __source: "slide" as const,
+    }))
 
-  slides.forEach((slide, index) => {
-    const slideElement = createSlideElement(size.width, size.height)
-    applySlideBackground(slideElement, slide.fill)
-    if (slide.layoutElements && Array.isArray(slide.layoutElements)) {
-      processElements(slide.layoutElements, index + 1)
-      slide.layoutElements.forEach((element) => {
-        const el = createElementByType(element)
-        if (!el) return
-        slideElement.appendChild(el)
-      })
+    const merged = [...layoutElements, ...slideElements]
+
+    const elements = merged
+      .filter((el) => el && typeof el === "object")
+      .slice()
+      .sort((a, b) => (getNumber(a.order) || 0) - (getNumber(b.order) || 0))
+
+    return {
+      ...slide,
+      elements,
     }
+  })
+})
+
+onMounted(() => {
+  if (!rootRef.value) return
+  console.log('props.pptxJson', props.pptxJson)
+  const updateWidth = () => {
+    if (!rootRef.value) return
+    containerWidth.value = rootRef.value.clientWidth
+  }
+  updateWidth()
+  resizeObserver = new ResizeObserver(() => updateWidth())
+  resizeObserver.observe(rootRef.value)
+})
+
+onBeforeUnmount(() => {
+  resizeObserver?.disconnect()
+  resizeObserver = null
+})
+
+function getNumber(value: unknown) {
+  const n = Number(value)
+  return Number.isFinite(n) ? n : 0
+}
+
+function sanitizeHtml(html: string) {
+  if (!html) return ""
+  try {
+    const parser = new DOMParser()
+    const doc = parser.parseFromString(html, "text/html")
+
+    const forbidden = ["script", "style", "iframe", "object", "embed", "link", "meta"]
+    forbidden.forEach((tag) => {
+      doc.querySelectorAll(tag).forEach((node) => node.remove())
+    })
+
+    doc.querySelectorAll("*").forEach((node) => {
+      Array.from(node.attributes).forEach((attr) => {
+        const name = attr.name.toLowerCase()
+        const value = String(attr.value || "").trim().toLowerCase()
+        if (name.startsWith("on")) node.removeAttribute(attr.name)
+        if ((name === "href" || name === "src") && value.startsWith("javascript:")) {
+          node.removeAttribute(attr.name)
+        }
+      })
+
+      const style = node.getAttribute("style")
+      if (style) {
+        const replaced = style.replace(/font-size\s*:\s*([\d.]+)pt/gi, (_m, v) => {
+          const n = Number(v)
+          if (!Number.isFinite(n)) return _m
+          const px = (n * 96) / 72
+          return `font-size: ${px.toFixed(3).replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1")}px`
+        })
+        if (replaced !== style) node.setAttribute("style", replaced)
+      }
+    })
+
+    return doc.body.innerHTML
+  } catch {
+    return html
+  }
+}
+
+function getElementKey(el: PptxElement, elementIndex: number) {
+  const stable = getNumber(el.order) || elementIndex
+  return `${el.type || "el"}-${stable}`
+}
 
-    // 渲染幻灯片元素
-    if (slide.elements && Array.isArray(slide.elements)) {
-      processElements(slide.elements, index + 1)
-      slide.elements.forEach((element) => {
-        const el = createElementByType(element)
-        if (!el) return
-        slideElement.appendChild(el)
+function getElementCacheId(el: PptxElement, elementIndex: number, parentCacheId?: string) {
+  const stable = getNumber(el.order) || elementIndex
+  const t = String(el.type || "el")
+  const self = `${t}-${stable}`
+  return parentCacheId ? `${parentCacheId}/${self}` : self
+}
+
+function getSlideShellStyle() {
+  return {
+    width: `${Math.round(size.value.width * scale.value)}px`,
+    height: `${Math.round(size.value.height * scale.value)}px`,
+  } as CSSProperties
+}
+
+function getSlideStyle(slide: PptxSlide) {
+  const background = getSlideBackground(slide.fill)
+  return {
+    width: `${size.value.width}px`,
+    height: `${size.value.height}px`,
+    transform: `scale(${scale.value})`,
+    background,
+  } as CSSProperties
+}
+
+function getSlideBackground(fill?: PptxFill) {
+  if (!fill || !fill.type) return "#fff"
+  if (fill.type === "color") return String(fill.value || "#fff")
+  if (fill.type === "gradient") {
+    const colors = Array.isArray(fill.value?.colors) ? fill.value.colors : []
+    const rot = getNumber(fill.value?.rot)
+    const path = String(fill.value?.path || "rect")
+    const stops = colors
+      .map((c: any) => {
+        const pos = String(c?.pos ?? "")
+        const color = String(c?.color ?? "")
+        if (!color) return ""
+        return pos ? `${color} ${pos}` : color
       })
+      .filter(Boolean)
+      .join(", ")
+    if (!stops) return "#fff"
+    if (path === "rect") {
+      const angle = (90 - rot + 360) % 360
+      return `linear-gradient(${angle}deg, ${stops})`
     }
+    return `radial-gradient(circle, ${stops})`
+  }
+  if (fill.type === "image") {
+    const src = String(fill.value?.picBase64 || fill.value?.src || "")
+    if (!src) return "#fff"
+    return `center / cover no-repeat url(${src})`
+  }
+  return "#fff"
+}
 
-    // 添加幻灯片到容器
-    pptxContainer.value.appendChild(slideElement)
-  })
-  // 为所有p标签应用样式
-  const pTags = pptxContainer.value.querySelectorAll("p")
-  pTags.forEach((p) => {
-    p.style.margin = "0px"
-    p.style.padding = "0px"
-    p.style.wordBreak = "break-word"
-    p.style.lineHeight = "1"
-  })
-  const ulTags = pptxContainer.value.querySelectorAll("ul")
-  ulTags.forEach((ul) => {
-    ul.style.wordBreak = "break-word"
-    ul.style.lineHeight = "1"
-    ul.style.padding = "auto 0px"
-    ul.style.margin = "0px"
-  })
-  const olTags = pptxContainer.value.querySelectorAll("ol")
-  olTags.forEach((ol) => {
-    ol.style.margin = "0px"
-    ol.style.padding = "auto 0px"
-    ol.style.wordBreak = "break-word"
-    ol.style.lineHeight = "1"
-  })
+function getElementStyle(el: PptxElement, elementIndex: number) {
+  const left = getNumber(el.left)
+  const top = getNumber(el.top)
+  const width = Math.max(0, getNumber(el.width))
+  const height = Math.max(0, getNumber(el.height))
+
+  const rotate = getNumber(el.rotate)
+  const flipH = !!el.isFlipH
+  const flipV = !!el.isFlipV
+  const zIndex = getElementZIndex(el, elementIndex)
+  const opacity = el.opacity == null ? 1 : Math.max(0, Math.min(1, getNumber(el.opacity)))
+
+  const transforms: string[] = []
+  if (rotate) transforms.push(`rotate(${rotate}deg)`) 
+  if (flipH) transforms.push(`scaleX(-1)`) 
+  if (flipV) transforms.push(`scaleY(-1)`) 
+
+  const background = getElementBackground(el)
+  const border = getElementBorderCss(el)
+  const radius = getElementBorderRadius(el)
+  const shadowFilter = getElementShadowFilter(el)
+
+  return {
+    position: "absolute" as const,
+    left: `${left}px`,
+    top: `${top}px`,
+    width: `${width}px`,
+    height: `${height}px`,
+    zIndex,
+    opacity,
+    background,
+    border,
+    borderRadius: radius,
+    filter: shadowFilter,
+    transformOrigin: "center center",
+    transform: transforms.length ? transforms.join(" ") : undefined,
+  } as CSSProperties
+}
+
+function getElementZIndex(el: PptxElement, elementIndex: number) {
+  const base = getNumber(el.order) || elementIndex
+  const source = (el as any)?.__source
+  const offset = source === "slide" ? 100000 : 0
+  return base + offset
+}
+
+function getElementShadowFilter(el: PptxElement) {
+  const shadow = (el as any)?.shadow
+  if (!shadow || typeof shadow !== "object") return undefined
+  const h = getNumber((shadow as any).h)
+  const v = getNumber((shadow as any).v)
+  const blur = Math.max(0, getNumber((shadow as any).blur))
+  const color = String((shadow as any).color || "").trim()
+  if (!color || (!h && !v && !blur)) return undefined
+  return `drop-shadow(${h}px ${v}px ${blur}px ${color})`
+}
+
+function getElementBorderRadius(el: PptxElement) {
+  const candidates = [el.radius, el.cornerRadius, el.rx]
+  const r = candidates.map(getNumber).find((n) => n > 0) || 0
+  return r ? `${r}px` : undefined
 }
 
-// 创建幻灯片元素
-const createSlideElement = (width, height) => {
-  const slideElement = document.createElement("div")
-  slideElement.className = "slide"
-  slideElement.style.position = "relative"
-  slideElement.style.width = width + "px"
-  slideElement.style.height = height + "px"
-  slideElement.style.border = "1px solid #ccc"
-  slideElement.style.margin = "0px auto"
-  slideElement.style.marginBottom = "20px"
-  slideElement.style.overflow = "hidden"
-  return slideElement
+function getElementBorderCss(el: PptxElement) {
+  if (isShapeElement(el)) return undefined
+  const border = getBorderInfo(el)
+  if (!border.color || !border.width) return undefined
+  return `${border.width}px solid ${border.color}`
 }
 
-// 应用幻灯片背景
-const applySlideBackground = (slideElement, fill) => {
-  if (!fill) return
+function getElementBackground(el: PptxElement) {
+  if (isShapeElement(el) || isImageElement(el) || isVideoElement(el) || isAudioElement(el)) return undefined
 
+  if (typeof el.fill === "string") {
+    const raw = el.fill.trim()
+    return raw ? raw : undefined
+  }
+
+  const fill = typeof el.fill === "object" && el.fill ? (el.fill as PptxFill) : null
+  if (!fill || !fill.type) return undefined
+  if (fill.type === "color") return String(fill.value || "") || undefined
   if (fill.type === "gradient") {
-    const { colors, path, rot } = fill.value
+    const colors = Array.isArray(fill.value?.colors) ? fill.value.colors : []
+    const rot = getNumber(fill.value?.rot)
+    const path = String(fill.value?.path || "rect")
+    const stops = colors
+      .map((c: any) => {
+        const pos = String(c?.pos ?? "")
+        const color = String(c?.color ?? "")
+        if (!color) return ""
+        return pos ? `${color} ${pos}` : color
+      })
+      .filter(Boolean)
+      .join(", ")
+    if (!stops) return undefined
+    if (path === "rect") {
+      const angle = (90 - rot + 360) % 360
+      return `linear-gradient(${angle}deg, ${stops})`
+    }
+    return `radial-gradient(circle, ${stops})`
+  }
+  return undefined
+}
 
-    if (colors && colors.length >= 2) {
-      const gradientType = path === "rect" ? "linear" : "radial"
-      const gradientAngle =
-        gradientType === "linear" ? (90 - (rot || 0)) % 360 : rot || 0
+function getHtmlBoxStyle(el: PptxElement) {
+  const vAlign = String(el.vAlign || "up")
+  const justifyContent = vAlign === "down" ? "flex-end" : vAlign === "mid" ? "center" : "flex-start"
+  return {
+    width: "100%",
+    height: "100%",
+    display: "flex" as const,
+    flexDirection: "column" as const,
+    justifyContent,
+  } as CSSProperties
+}
+
+function getHtmlInnerStyle(el: PptxElement) {
+  const autoFit = (el as any)?.autoFit
+  const rawScale = autoFit && typeof autoFit === "object" ? getNumber(autoFit.fontScale) : 1
+  const fontScale = rawScale && rawScale !== 1 ? Math.max(0.1, Math.min(5, rawScale)) : 1
+
+  const isVertical = !!(el as any)?.isVertical
+  const writingMode = isVertical ? ("vertical-rl" as const) : undefined
+  const textOrientation = isVertical ? ("mixed" as const) : undefined
+
+  if (fontScale === 1) {
+    return {
+      width: "100%",
+      height: "100%",
+      writingMode,
+      textOrientation,
+    } as CSSProperties
+  }
 
-      let gradientString = `${gradientType}-gradient(`
-      if (gradientType === "linear") {
-        gradientString += `${gradientAngle}deg, `
+  const inv = 100 / fontScale
+  return {
+    width: `${inv}%`,
+    height: `${inv}%`,
+    transformOrigin: "top left",
+    transform: `scale(${fontScale})`,
+    writingMode,
+    textOrientation,
+  } as CSSProperties
+}
+
+function isShapeElement(el: PptxElement) {
+  return String(el.type || "").toLowerCase() === "shape"
+}
+
+function isImageElement(el: PptxElement) {
+  const t = String(el.type || "").toLowerCase()
+  if (t === "image" || t === "pic" || t === "picture") return true
+  const src = getMediaSrc(el)
+  return !!src && /^data:image\//i.test(src)
+}
+
+function isVideoElement(el: PptxElement) {
+  const t = String(el.type || "").toLowerCase()
+  if (t === "video") return true
+  const src = getMediaSrc(el)
+  return !!src && /^data:video\//i.test(src)
+}
+
+function isAudioElement(el: PptxElement) {
+  const t = String(el.type || "").toLowerCase()
+  if (t === "audio") return true
+  const src = getMediaSrc(el)
+  return !!src && /^data:audio\//i.test(src)
+}
+
+function isTableElement(el: PptxElement) {
+  return String(el.type || "").toLowerCase() === "table"
+}
+
+function isChartElement(el: PptxElement) {
+  const t = String(el.type || "").toLowerCase()
+  return t === "chart" || t === "charts"
+}
+
+function isGroupElement(el: PptxElement) {
+  const t = String(el.type || "").toLowerCase()
+  if (t === "group" || t === "groupshape" || t === "grpsp" || t === "grp") return true
+  const hasChildren = Array.isArray((el as any)?.elements) && (el as any).elements.length
+  return hasChildren && t.includes("group")
+}
+
+function isDiagramElement(el: PptxElement) {
+  const t = String(el.type || "").toLowerCase()
+  return t === "diagram" || t === "smartart" || t === "smart_art"
+}
+
+function isMathElement(el: PptxElement) {
+  return String(el.type || "").toLowerCase() === "math"
+}
+
+function getGroupChildren(el: PptxElement) {
+  const raw = (el as any)?.elements
+  return Array.isArray(raw) ? (raw as PptxElement[]) : ([] as PptxElement[])
+}
+
+function getGroupChildStyle(parent: PptxElement, child: PptxElement, childIndex: number, parentAbsLeft: number, parentAbsTop: number) {
+  const parentW = Math.max(0, getNumber(parent.width))
+  const parentH = Math.max(0, getNumber(parent.height))
+
+  const rawLeft = getNumber(child.left)
+  const rawTop = getNumber(child.top)
+  const childW = Math.max(0, getNumber(child.width))
+  const childH = Math.max(0, getNumber(child.height))
+
+  const isRelative =
+    rawLeft >= -0.5 &&
+    rawTop >= -0.5 &&
+    rawLeft + childW <= parentW + 0.5 &&
+    rawTop + childH <= parentH + 0.5
+
+  const left = isRelative ? rawLeft : rawLeft - parentAbsLeft
+  const top = isRelative ? rawTop : rawTop - parentAbsTop
+
+  const width = childW
+  const height = childH
+
+  const rotate = getNumber(child.rotate)
+  const flipH = !!child.isFlipH
+  const flipV = !!child.isFlipV
+  const zIndex = getNumber(child.order) || childIndex
+  const opacity = child.opacity == null ? 1 : Math.max(0, Math.min(1, getNumber(child.opacity)))
+
+  const transforms: string[] = []
+  if (rotate) transforms.push(`rotate(${rotate}deg)`)
+  if (flipH) transforms.push(`scaleX(-1)`)
+  if (flipV) transforms.push(`scaleY(-1)`)
+
+  const background = getElementBackground(child)
+  const border = getElementBorderCss(child)
+  const radius = getElementBorderRadius(child)
+  const shadowFilter = getElementShadowFilter(child)
+
+  return {
+    position: "absolute" as const,
+    left: `${left}px`,
+    top: `${top}px`,
+    width: `${width}px`,
+    height: `${height}px`,
+    zIndex,
+    opacity,
+    background,
+    border,
+    borderRadius: radius,
+    filter: shadowFilter,
+    transformOrigin: "center center",
+    transform: transforms.length ? transforms.join(" ") : undefined,
+  } as CSSProperties
+}
+
+type GroupRenderProps = {
+  el: PptxElement
+  slideIndex: number
+  cacheId: string
+  absLeft: number
+  absTop: number
+}
+
+const PptxGroup = defineComponent<GroupRenderProps>({
+  name: "PptxGroup",
+  props: {
+    el: { type: Object as any, required: true },
+    slideIndex: { type: Number, required: true },
+    cacheId: { type: String, required: true },
+    absLeft: { type: Number, required: true },
+    absTop: { type: Number, required: true },
+  },
+  setup(groupProps) {
+    const renderShapeDefs = (el: PptxElement, slideIndex: number, cacheId: string) => {
+      if (!hasShapeDefs(el, slideIndex, cacheId)) return null
+
+      const grad = getShapeGradient(el, slideIndex, cacheId)
+      const pattern = getShapePattern(el, slideIndex, cacheId)
+      const paint = getShapeImagePaint(el, slideIndex, cacheId)
+
+      const nodes: any[] = []
+      if (grad?.kind === "linear") {
+        nodes.push(
+          h(
+            "linearGradient",
+            { id: grad.id, x1: grad.x1, y1: grad.y1, x2: grad.x2, y2: grad.y2 },
+            grad.stops.map((s, i) => h("stop", { key: i, offset: s.offset, "stop-color": s.color, "stop-opacity": s.opacity }))
+          )
+        )
+      } else if (grad?.kind === "radial") {
+        nodes.push(
+          h(
+            "radialGradient",
+            { id: grad.id, cx: "50%", cy: "50%", r: "50%" },
+            grad.stops.map((s, i) => h("stop", { key: i, offset: s.offset, "stop-color": s.color, "stop-opacity": s.opacity }))
+          )
+        )
       }
 
-      colors.forEach((color, i) => {
-        gradientString += `${color.color} ${color.pos}${
-          i < colors.length - 1 ? ", " : ""
-        }`
-      })
+      if (pattern) {
+        nodes.push(
+          h(
+            "pattern",
+            { id: pattern.id, patternUnits: "userSpaceOnUse", width: pattern.width, height: pattern.height },
+            [
+              h("rect", { x: 0, y: 0, width: pattern.width, height: pattern.height, fill: pattern.background }),
+              ...pattern.shapes.map((shape, i) => {
+                if (shape.kind === "circle") return h("circle", { key: i, cx: shape.cx, cy: shape.cy, r: shape.r, fill: shape.fill })
+                if (shape.kind === "polygon") return h("polygon", { key: i, points: shape.points, fill: shape.fill })
+                return h("rect", {
+                  key: i,
+                  x: (shape as any).x,
+                  y: (shape as any).y,
+                  width: (shape as any).width,
+                  height: (shape as any).height,
+                  fill: (shape as any).fill,
+                  transform: (shape as any).transform,
+                })
+              }),
+            ]
+          )
+        )
+      }
 
-      gradientString += ")"
-      slideElement.style.background = gradientString
+      if (paint) {
+        nodes.push(
+          h(
+            "pattern",
+            { id: paint.id, patternUnits: "objectBoundingBox", width: 1, height: 1 },
+            [
+              h("image", { x: 0, y: 0, width: 1, height: 1, preserveAspectRatio: "none", href: paint.href }),
+            ]
+          )
+        )
+      }
+
+      return nodes.length ? h("defs", null, nodes) : null
     }
-  } else if (fill.type === "color") {
-    slideElement.style.backgroundColor = fill.value || "#FFFFFF"
-  } else if (fill.type === "image" && fill.value.picBase64) {
-    // 设置背景图片
-    slideElement.style.backgroundImage = `url(${fill.value.picBase64})`
-    slideElement.style.backgroundSize = "cover"
-    slideElement.style.backgroundPosition = "center"
-    slideElement.style.backgroundRepeat = "no-repeat"
-
-    // 如果有背景图片的混合模式
-    if (fill.value.blendMode) {
-      slideElement.style.backgroundBlendMode = fill.value.blendMode
+
+    const renderElement = (child: PptxElement, childIndex: number, parentEl: PptxElement, parentAbsLeft: number, parentAbsTop: number, parentCacheId: string) => {
+      const style = getGroupChildStyle(parentEl, child, childIndex, parentAbsLeft, parentAbsTop)
+      const cacheId = getElementCacheId(child, childIndex, parentCacheId)
+      const left = getNumber((style as any)?.left)
+      const top = getNumber((style as any)?.top)
+      const absLeft = parentAbsLeft + left
+      const absTop = parentAbsTop + top
+
+      if (isImageElement(child)) {
+        return h(
+          "div",
+          { key: cacheId, class: "pptx-element", style },
+          [
+            h(
+              "div",
+              { class: "pptx-img-wrap", style: getImageWrapStyle(child) },
+              [h("img", { class: "pptx-img", src: getMediaSrc(child), style: getImageStyle(child), alt: "", draggable: false })]
+            ),
+          ]
+        )
+      }
+
+      if (isVideoElement(child)) {
+        return h("div", { key: cacheId, class: "pptx-element", style }, [h("video", { class: "pptx-media", src: getMediaSrc(child), controls: true, preload: "metadata" })])
+      }
+
+      if (isAudioElement(child)) {
+        return h("div", { key: cacheId, class: "pptx-element", style }, [h("audio", { class: "pptx-media", src: getMediaSrc(child), controls: true, preload: "metadata" })])
+      }
+
+      if (isMathElement(child)) {
+        return h("div", { key: cacheId, class: "pptx-element", style }, [h("img", { class: "pptx-img", src: getMediaSrc(child), alt: "", draggable: false })])
+      }
+
+      if (isChartElement(child)) {
+        const model = getChartModel(child, groupProps.slideIndex, cacheId)
+        const nodes: any[] = []
+
+        if (model.kind === "bar") {
+          nodes.push(...model.bars.map((b, i) => h("rect", { key: i, x: b.x, y: b.y, width: b.w, height: b.h, fill: b.fill, "fill-opacity": b.opacity })))
+        } else if (model.kind === "line") {
+          nodes.push(
+            ...model.paths.map((p, i) =>
+              h("path", { key: i, d: p.d, fill: "none", stroke: p.stroke, "stroke-width": p.strokeWidth, "stroke-linejoin": "round", "stroke-linecap": "round" })
+            )
+          )
+          nodes.push(...model.points.map((pt, i) => h("circle", { key: i, cx: pt.cx, cy: pt.cy, r: pt.r, fill: pt.fill, "fill-opacity": pt.opacity })))
+        } else if (model.kind === "pie") {
+          nodes.push(...model.slices.map((s, i) => h("path", { key: i, d: s.d, fill: s.fill, "fill-opacity": s.opacity })))
+          if (model.holeR) nodes.push(h("circle", { cx: model.cx, cy: model.cy, r: model.holeR, fill: "#fff" }))
+        } else if (model.kind === "scatter") {
+          nodes.push(...model.points.map((pt, i) => h("circle", { key: i, cx: pt.cx, cy: pt.cy, r: pt.r, fill: pt.fill, "fill-opacity": pt.opacity })))
+        }
+
+        return h(
+          "div",
+          { key: cacheId, class: "pptx-element", style },
+          [h("svg", { class: "pptx-chart", viewBox: `0 0 ${getNumber(child.width)} ${getNumber(child.height)}`, preserveAspectRatio: "none" }, nodes)]
+        )
+      }
+
+      if (isTableElement(child)) {
+        const model = getTableModel(child, groupProps.slideIndex, cacheId)
+        return h(
+          "div",
+          { key: cacheId, class: "pptx-element", style },
+          [
+            h(
+              "div",
+              { class: "pptx-table-wrap" },
+              [
+                h(
+                  "table",
+                  { class: "pptx-table" },
+                  [
+                    model.colWidths.length
+                      ? h(
+                          "colgroup",
+                          null,
+                          model.colWidths.map((w, i) => h("col", { key: i, style: { width: w ? `${w}px` : undefined } }))
+                        )
+                      : null,
+                    h(
+                      "tbody",
+                      null,
+                      model.rows.map((row, ri) =>
+                        h(
+                          "tr",
+                          { key: ri, style: getTableRowStyle(child, groupProps.slideIndex, cacheId, ri) },
+                          row
+                            .map((cell, ci) => {
+                              if (cell.skip) return null
+                              return h(
+                                "td",
+                                { key: `${ri}-${ci}`, colspan: cell.colspan, rowspan: cell.rowspan, style: cell.style },
+                                [h("div", { class: "pptx-table-html", innerHTML: sanitizeHtml(cell.html) })]
+                              )
+                            })
+                            .filter(Boolean)
+                        )
+                      )
+                    ),
+                  ].filter(Boolean) as any
+                ),
+              ]
+            ),
+          ]
+        )
+      }
+
+      if (isShapeElement(child)) {
+        const defs = renderShapeDefs(child, groupProps.slideIndex, cacheId)
+        const svg = h(
+          "svg",
+          { class: "pptx-shape-svg", viewBox: `0 0 ${getNumber(child.width)} ${getNumber(child.height)}`, preserveAspectRatio: "none" },
+          [
+            defs,
+            h("path", {
+              d: getShapePath(child),
+              fill: getShapeFill(child, groupProps.slideIndex, cacheId),
+              stroke: getShapeStroke(child),
+              "stroke-width": getShapeStrokeWidth(child),
+              "stroke-dasharray": getShapeDasharray(child),
+            }),
+          ].filter(Boolean) as any
+        )
+
+        const html = typeof child.content === "string" && child.content.trim()
+        const overlay = html
+          ? h(
+              "div",
+              { class: "pptx-html", style: getHtmlBoxStyle(child) },
+              [h("div", { class: "pptx-html-inner", style: getHtmlInnerStyle(child), innerHTML: sanitizeHtml(child.content as string) })]
+            )
+          : null
+
+        return h("div", { key: cacheId, class: "pptx-element", style }, [svg, overlay].filter(Boolean) as any)
+      }
+
+      if (isGroupElement(child) || isDiagramElement(child)) {
+        return h(
+          "div",
+          { key: cacheId, class: "pptx-element", style },
+          [h(PptxGroup as any, { el: child, slideIndex: groupProps.slideIndex, cacheId, absLeft, absTop })]
+        )
+      }
+
+      const html = typeof child.content === "string" && child.content.trim()
+      return h(
+        "div",
+        { key: cacheId, class: "pptx-element", style },
+        html
+          ? [
+              h(
+                "div",
+                { class: "pptx-html", style: getHtmlBoxStyle(child) },
+                [h("div", { class: "pptx-html-inner", style: getHtmlInnerStyle(child), innerHTML: sanitizeHtml(child.content as string) })]
+              ),
+            ]
+          : []
+      )
     }
 
-    // 如果有透明度设置
-    if (fill.value.opacity !== undefined) {
-      slideElement.style.opacity = fill.value.opacity
+    return () => {
+      const children = getGroupChildren(groupProps.el)
+      return h(
+        "div",
+        { class: "pptx-group-inner" },
+        children.map((child, idx) => renderElement(child, idx, groupProps.el, groupProps.absLeft, groupProps.absTop, groupProps.cacheId))
+      )
     }
+  },
+})
+
+function normalizeRatio(n: unknown) {
+  const v = getNumber(n)
+  if (!v) return 0
+  if (v > 1) return Math.max(0, Math.min(1, v / 100))
+  return Math.max(0, Math.min(1, v))
+}
+
+function getImageCropRect(el: PptxElement) {
+  const rect = (el as any)?.rect
+  const crop = (el as any)?.crop
+  const raw = rect && typeof rect === "object" ? rect : crop && typeof crop === "object" ? crop : null
+  if (!raw) return null
+
+  const t = normalizeRatio(raw.t)
+  const b = normalizeRatio(raw.b)
+  const l = normalizeRatio(raw.l)
+  const r = normalizeRatio(raw.r)
+  if (!t && !b && !l && !r) return null
+
+  const safeL = Math.max(0, Math.min(0.9, l))
+  const safeR = Math.max(0, Math.min(0.9, r))
+  const safeT = Math.max(0, Math.min(0.9, t))
+  const safeB = Math.max(0, Math.min(0.9, b))
+  if (safeL + safeR >= 0.98 || safeT + safeB >= 0.98) return null
+  return { t: safeT, b: safeB, l: safeL, r: safeR }
+}
+
+function getImageGeom(el: PptxElement) {
+  const g = String((el as any)?.geom || (el as any)?.shapeType || "").toLowerCase()
+  return g
+}
+
+function getImageWrapStyle(el: PptxElement) {
+  const geom = getImageGeom(el)
+  const isEllipse = geom === "ellipse" || geom === "circle"
+  const borderRadius = isEllipse ? "50%" : getElementBorderRadius(el)
+  return {
+    width: "100%",
+    height: "100%",
+    position: "relative" as const,
+    overflow: "hidden",
+    borderRadius,
+  } as CSSProperties
+}
+
+function normalizeFilterFactor(value: unknown, base = 1) {
+  if (value == null) return base
+  const n = getNumber(value)
+  if (!n) return base
+  const v = n > 10 ? n / 100 : n
+  return Math.max(0, Math.min(3, v))
+}
+
+function buildImageFilter(el: PptxElement) {
+  const filters = (el as any)?.filters
+  if (!filters || typeof filters !== "object") return undefined
+
+  const brightness = normalizeFilterFactor(filters.brightness, 1)
+  const contrast = normalizeFilterFactor(filters.contrast, 1)
+  const saturation = normalizeFilterFactor(filters.saturation, 1)
+  const colorTemperature = getNumber(filters.colorTemperature)
+
+  const parts: string[] = []
+  if (brightness !== 1) parts.push(`brightness(${brightness})`)
+  if (contrast !== 1) parts.push(`contrast(${contrast})`)
+  if (saturation !== 1) parts.push(`saturate(${saturation})`)
+  if (colorTemperature) {
+    const t = Math.max(-100, Math.min(100, colorTemperature))
+    const hue = t * 0.6
+    const sepia = Math.min(1, Math.abs(t) / 200)
+    parts.push(`hue-rotate(${hue}deg)`)
+    if (t > 0 && sepia) parts.push(`sepia(${sepia})`)
   }
+  return parts.length ? parts.join(" ") : undefined
 }
 
-// 根据元素类型创建DOM元素
-const createElementByType = (element) => {
-  switch (element.type) {
-    case "image":
-      return createImageElement(element)
-    case "video":
-      return createVideoElement(element)
-    case "audio":
-      return createAudioElement(element)
-    case "shape":
-      return createShapeElement(element)
-    case "table":
-      return createTableElement(element)
-    case "chart":
-      return createChartElement(element)
-    case "diagram":
-      return createDiagramElement(element)
-    case "math":
-      return createMathElement(element)
-    case "group":
-      return createGroupElement(element)
-    default:
-      return createTextElement(element)
-  }
-}
-
-// 创建组合元素
-const createGroupElement = (element) => {
-  // 创建组合容器
-  const groupContainer = document.createElement("div")
-  groupContainer.className = "group-element"
-  groupContainer.style.position = "absolute"
-  groupContainer.style.top = element.top + "px"
-  groupContainer.style.left = element.left + "px"
-  groupContainer.style.width = element.width + "px"
-  groupContainer.style.height = element.height + "px"
-  groupContainer.style.zIndex = element.order
-  groupContainer.style.transformOrigin = "center center"
-
-  // 创建内部容器来处理子元素
-  const innerContainer = document.createElement("div")
-  innerContainer.style.position = "relative"
-  innerContainer.style.width = "100%"
-  innerContainer.style.height = "100%"
-
-  // 应用旋转变换
-  if (element.rotate) {
-    groupContainer.style.transform = `rotate(${element.rotate}deg)`
-  }
-
-  // 应用其他样式属性
-  if (element.opacity !== undefined) {
-    groupContainer.style.opacity = element.opacity
-  }
-
-  // 递归渲染组内的所有子元素
-  if (element.elements && Array.isArray(element.elements)) {
-    element.elements.forEach((childElement) => {
-      const childCopy = JSON.parse(JSON.stringify(childElement))
-      const childEl = createElementByType(childCopy)
-      if (childEl) {
-        innerContainer.appendChild(childEl)
-      }
-    })
+function getImageStyle(el: PptxElement) {
+  const crop = getImageCropRect(el)
+  const filter = buildImageFilter(el)
+
+  if (!crop) {
+    return {
+      width: "100%",
+      height: "100%",
+      objectFit: "contain",
+      filter,
+      display: "block",
+    } as CSSProperties
   }
 
-  groupContainer.appendChild(innerContainer)
-  return groupContainer
-}
-// 递归调整元素位置
-const adjustElementPosition = (element, parentElement) => {
-  // 创建深拷贝,但保留特殊属性的引用
-  const adjustedElement = JSON.parse(JSON.stringify(element))
-
-  // 调整位置为相对于父组合元素的位置
-  adjustedElement.top = element.top - parentElement.top
-  adjustedElement.left = element.left - parentElement.left
-
-  // 恢复特殊属性的引用
-  const specialProps = [
-    "src",
-    "blob",
-    "fill",
-    "text",
-    "path",
-    "elements",
-    "borderColor",
-    "borderWidth",
-    "borderType",
+  const scaleX = 1 / (1 - crop.l - crop.r)
+  const scaleY = 1 / (1 - crop.t - crop.b)
+  const translateX = -crop.l * 100
+  const translateY = -crop.t * 100
+
+  return {
+    width: "100%",
+    height: "100%",
+    objectFit: "fill",
+    display: "block",
+    transformOrigin: "top left",
+    transform: `translate(${translateX}%, ${translateY}%) scale(${scaleX}, ${scaleY})`,
+    filter,
+  } as CSSProperties
+}
+
+function getMediaSrc(el: PptxElement) {
+  const fillObj = typeof el.fill === "object" && el.fill ? (el.fill as PptxFill) : null
+  const candidates = [
+    el.src,
+    el.url,
+    el.picBase64,
+    el.mediaBase64,
+    el.base64,
+    el.blob,
+    el.blobUrl,
+    el.value?.picBase64,
+    el.value?.src,
+    fillObj?.value?.picBase64,
+    fillObj?.value?.src,
   ]
-  specialProps.forEach((prop) => {
-    if (element[prop] !== undefined) {
-      adjustedElement[prop] = element[prop]
+  const found = candidates.find((v) => typeof v === "string" && v.trim())
+  return found ? String(found) : ""
+}
+
+type ChartBar = { x: number; y: number; w: number; h: number; fill: string; opacity?: number }
+type ChartPath = { d: string; stroke: string; strokeWidth: number }
+type ChartPoint = { cx: number; cy: number; r: number; fill: string; opacity?: number }
+type ChartSlice = { d: string; fill: string; opacity?: number }
+
+type ChartModel = {
+  kind: "bar" | "line" | "pie" | "scatter"
+  bars: ChartBar[]
+  paths: ChartPath[]
+  points: ChartPoint[]
+  slices: ChartSlice[]
+  cx: number
+  cy: number
+  holeR: number
+}
+
+const chartCache = new Map<string, ChartModel>()
+
+function getChartModel(el: PptxElement, slideIndex: number, cacheId: string): ChartModel {
+  const key = `c-${getCacheKey(slideIndex, cacheId)}`
+  const cached = chartCache.get(key)
+  if (cached) return cached
+
+  const w = Math.max(1, getNumber(el.width))
+  const h = Math.max(1, getNumber(el.height))
+  const chartType = String((el as any)?.chartType || "").toLowerCase()
+  const colorsRaw = Array.isArray((el as any)?.colors) ? ((el as any).colors as string[]) : []
+  const colors = colorsRaw.length ? colorsRaw.map((c) => String(c || "").trim()).filter(Boolean) : []
+  const getColor = (i: number) => colors[i % Math.max(1, colors.length)] || "#4e79a7"
+
+  const opacity = el.opacity == null ? 1 : Math.max(0, Math.min(1, getNumber(el.opacity)))
+  const padding = Math.max(4, Math.min(24, Math.round(Math.min(w, h) * 0.08)))
+
+  const isPie = chartType.includes("pie") || chartType.includes("doughnut")
+  const isBar = chartType.includes("bar") || chartType.includes("col")
+  const isScatter = chartType.includes("scatter") || chartType.includes("bubble")
+
+  if (isScatter) {
+    const data = (el as any)?.data
+    const xs = Array.isArray(data?.[0]) ? (data[0] as number[]) : []
+    const ys = Array.isArray(data?.[1]) ? (data[1] as number[]) : []
+    const n = Math.min(xs.length, ys.length)
+    const minX = n ? Math.min(...xs.slice(0, n)) : 0
+    const maxX = n ? Math.max(...xs.slice(0, n)) : 1
+    const minY = n ? Math.min(...ys.slice(0, n)) : 0
+    const maxY = n ? Math.max(...ys.slice(0, n)) : 1
+    const spanX = maxX - minX || 1
+    const spanY = maxY - minY || 1
+    const innerW = Math.max(1, w - padding * 2)
+    const innerH = Math.max(1, h - padding * 2)
+
+    const points: ChartPoint[] = []
+    for (let i = 0; i < n; i++) {
+      const x = padding + ((xs[i] - minX) / spanX) * innerW
+      const y = padding + (1 - (ys[i] - minY) / spanY) * innerH
+      points.push({ cx: x, cy: y, r: 3, fill: getColor(0), opacity })
     }
-  })
+    const model: ChartModel = { kind: "scatter", bars: [], paths: [], points, slices: [], cx: 0, cy: 0, holeR: 0 }
+    chartCache.set(key, model)
+    return model
+  }
 
-  // 如果是组合元素,递归处理其子元素
-  if (element.type === "group" && element.elements) {
-    adjustedElement.elements = element.elements.map((childElement) =>
-      adjustElementPosition(childElement, {
-        top: element.top,
-        left: element.left,
-      })
+  const rawData = (el as any)?.data
+
+  if (isPie) {
+    const series = Array.isArray(rawData) ? (rawData as any[]) : []
+    const valuesRaw = Array.isArray(series?.[0]?.values) ? (series[0].values as any[]) : []
+    const values = valuesRaw
+      .map((v) => ({ y: getNumber(v?.y), x: String(v?.x ?? "") }))
+      .filter((v) => Number.isFinite(v.y) && v.y > 0)
+    const sum = values.reduce((acc, v) => acc + v.y, 0) || 1
+
+    const cx = w / 2
+    const cy = h / 2
+    const r = Math.max(2, Math.min(w, h) / 2 - padding)
+
+    const holeSize = String((el as any)?.holeSize || "").trim()
+    const holeRatio = holeSize.endsWith("%") ? getNumber(holeSize.replace("%", "")) / 100 : getNumber(holeSize)
+    const holeR = Math.max(0, Math.min(r - 1, r * Math.max(0, Math.min(0.9, holeRatio || 0))))
+
+    let start = -Math.PI / 2
+    const slices: ChartSlice[] = values.map((v, i) => {
+      const a = (v.y / sum) * Math.PI * 2
+      const end = start + a
+      const x1 = cx + r * Math.cos(start)
+      const y1 = cy + r * Math.sin(start)
+      const x2 = cx + r * Math.cos(end)
+      const y2 = cy + r * Math.sin(end)
+      const large = a > Math.PI ? 1 : 0
+      const d = `M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${large} 1 ${x2} ${y2} Z`
+      start = end
+      return { d, fill: getColor(i), opacity }
+    })
+    const model: ChartModel = { kind: "pie", bars: [], paths: [], points: [], slices, cx, cy, holeR }
+    chartCache.set(key, model)
+    return model
+  }
+
+  const series = Array.isArray(rawData) ? (rawData as any[]) : []
+  const items = series
+    .map((s) => {
+      const values = Array.isArray(s?.values) ? (s.values as any[]) : []
+      return {
+        key: String(s?.key || ""),
+        values: values.map((v) => ({ x: String(v?.x ?? ""), y: getNumber(v?.y) })),
+      }
+    })
+    .filter((s) => s.values.length)
+
+  const categories = Array.from(
+    new Set(
+      items
+        .flatMap((s) => s.values.map((v) => v.x))
+        .filter((x) => x != null)
+        .map((x) => String(x))
     )
+  )
+  const catCount = Math.max(1, categories.length)
+  const seriesCount = Math.max(1, items.length)
+
+  const maxY = Math.max(
+    1,
+    ...items.flatMap((s) => s.values.map((v) => v.y)).filter((v) => Number.isFinite(v))
+  )
+
+  const innerW = Math.max(1, w - padding * 2)
+  const innerH = Math.max(1, h - padding * 2)
+
+  const barDir = String((el as any)?.barDir || "col").toLowerCase()
+
+  if (isBar) {
+    const bars: ChartBar[] = []
+
+    if (barDir === "bar") {
+      const bandH = innerH / catCount
+      const barH = bandH * 0.8
+      const gapY = (bandH - barH) / 2
+      const eachH = barH / seriesCount
+
+      for (let ci = 0; ci < catCount; ci++) {
+        for (let si = 0; si < items.length; si++) {
+          const v = items[si].values.find((vv) => vv.x === categories[ci])
+          const value = v ? v.y : 0
+          const bw = (value / maxY) * innerW
+          const x = padding
+          const y = padding + ci * bandH + gapY + si * eachH
+          bars.push({ x, y, w: Math.max(0, bw), h: Math.max(0, eachH * 0.9), fill: getColor(si), opacity })
+        }
+      }
+    } else {
+      const bandW = innerW / catCount
+      const barW = bandW * 0.8
+      const gapX = (bandW - barW) / 2
+      const eachW = barW / seriesCount
+
+      for (let ci = 0; ci < catCount; ci++) {
+        for (let si = 0; si < items.length; si++) {
+          const v = items[si].values.find((vv) => vv.x === categories[ci])
+          const value = v ? v.y : 0
+          const bh = (value / maxY) * innerH
+          const x = padding + ci * bandW + gapX + si * eachW
+          const y = padding + (innerH - bh)
+          bars.push({ x, y, w: Math.max(0, eachW * 0.9), h: Math.max(0, bh), fill: getColor(si), opacity })
+        }
+      }
+    }
+
+    const model: ChartModel = { kind: "bar", bars, paths: [], points: [], slices: [], cx: 0, cy: 0, holeR: 0 }
+    chartCache.set(key, model)
+    return model
   }
 
-  return adjustedElement
+  const paths: ChartPath[] = []
+  const points: ChartPoint[] = []
+  const strokeWidth = Math.max(1, Math.round(Math.min(w, h) * 0.01))
+  const marker = !!(el as any)?.marker
+
+  const xAt = (i: number) => padding + (catCount === 1 ? innerW / 2 : (i / (catCount - 1)) * innerW)
+  const yAt = (value: number) => padding + (1 - value / maxY) * innerH
+
+  items.forEach((s, si) => {
+    let d = ""
+    categories.forEach((cat, ci) => {
+      const v = s.values.find((vv) => vv.x === cat)
+      const value = v ? v.y : 0
+      const x = xAt(ci)
+      const y = yAt(value)
+      d += ci === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`
+      if (marker) points.push({ cx: x, cy: y, r: strokeWidth * 0.9 + 1, fill: getColor(si), opacity })
+    })
+    paths.push({ d, stroke: getColor(si), strokeWidth })
+  })
+
+  const model: ChartModel = { kind: "line", bars: [], paths, points, slices: [], cx: 0, cy: 0, holeR: 0 }
+  chartCache.set(key, model)
+  return model
 }
 
-const processElements = (elements, slideIndex) => {
-  if (!elements || !Array.isArray(elements)) return
+type TableBorderSide = {
+  borderColor?: string
+  borderWidth?: number
+  borderType?: string
+  strokeDasharray?: string
+}
 
-  // 使用 Map 存储原始顺序,避免多次排序
-  const orderMap = new Map(elements.map((el, index) => [el, el.order || index]))
+type TableCellRaw = {
+  text?: string
+  content?: string
+  html?: string
+  colSpan?: number
+  rowSpan?: number
+  hMerge?: number
+  vMerge?: number
+  fillColor?: string
+  fontColor?: string
+  fontBold?: boolean
+  fontItalic?: boolean
+  borders?: {
+    top?: TableBorderSide
+    right?: TableBorderSide
+    bottom?: TableBorderSide
+    left?: TableBorderSide
+  }
+  [key: string]: any
+}
 
-  // 一次性排序
-  elements.sort((a, b) => orderMap.get(a) - orderMap.get(b))
+type TableCellView = {
+  html: string
+  colspan: number
+  rowspan: number
+  skip: boolean
+  style: CSSProperties
+}
 
-  const processElement = (element, baseOrder) => {
-    // 设置当前元素的 order
-    element.order = baseOrder
+type TableModel = {
+  colWidths: number[]
+  rowHeights: number[]
+  rows: TableCellView[][]
+}
 
-    // 如果有子元素,递归处理
-    if (element.elements && element.elements.length > 0) {
-      element.elements
-        .sort((a, b) => {
-          return (a.order || 0) - (b.order || 0)
-        })
-        .forEach((child, idx) => {
-          processElement(child, baseOrder + idx + 2)
-        })
+const tableCache = new Map<string, TableModel>()
+
+function getTableModel(el: PptxElement, slideIndex: number, cacheId: string): TableModel {
+  const key = `t-${getCacheKey(slideIndex, cacheId)}`
+  const cached = tableCache.get(key)
+  if (cached) return cached
+
+  const rawData = (el as any)?.data
+  const data: TableCellRaw[][] = Array.isArray(rawData) ? rawData : []
+  const colWidthsRaw = (el as any)?.colWidths
+  const rowHeightsRaw = (el as any)?.rowHeights
+  const colWidths = Array.isArray(colWidthsRaw) ? colWidthsRaw.map(getNumber) : []
+  const rowHeights = Array.isArray(rowHeightsRaw) ? rowHeightsRaw.map(getNumber) : []
+
+  const rows: TableCellView[][] = data.map((row) => {
+    const r = Array.isArray(row) ? row : []
+    return r.map((cellRaw) => normalizeTableCell(el, cellRaw))
+  })
+
+  const model: TableModel = {
+    colWidths,
+    rowHeights,
+    rows,
+  }
+  tableCache.set(key, model)
+  return model
+}
+
+function getTableRowStyle(el: PptxElement, slideIndex: number, cacheId: string, rowIndex: number) {
+  const model = getTableModel(el, slideIndex, cacheId)
+  const h = model.rowHeights[rowIndex]
+  if (!h) return undefined
+  return {
+    height: `${h}px`,
+  } as CSSProperties
+}
+
+function extractTextAlign(html: string) {
+  const m = html.match(/text-align\s*:\s*(left|right|center|justify)/i)
+  return m ? m[1].toLowerCase() : "left"
+}
+
+function getTableBorderStyle(side?: TableBorderSide) {
+  if (!side) return ""
+  const color = String(side.borderColor || "")
+  const width = Math.max(0, getNumber(side.borderWidth))
+  const borderType = String(side.borderType || "solid")
+  if (!color || !width) return ""
+  const style = borderType === "dashed" || borderType === "dash" ? "dashed" : "solid"
+  return `${width}px ${style} ${color}`
+}
+
+function normalizeTableCell(tableEl: PptxElement, cellRaw: TableCellRaw): TableCellView {
+  const raw = cellRaw && typeof cellRaw === "object" ? cellRaw : ({} as TableCellRaw)
+
+  const html = String(raw.text ?? raw.content ?? raw.html ?? "")
+  const colspan = Math.max(1, getNumber(raw.colSpan ?? raw.colspan ?? raw.gridSpan) || 1)
+  const rowspan = Math.max(1, getNumber(raw.rowSpan ?? raw.rowspan) || 1)
+  const skip = getNumber(raw.hMerge) === 1 || getNumber(raw.vMerge) === 1
+
+  const background = String(raw.fillColor || "") || undefined
+  const color = String(raw.fontColor || "") || undefined
+  const fontWeight = raw.fontBold ? 700 : undefined
+  const fontStyle = raw.fontItalic ? "italic" : undefined
+  const textAlign = html ? extractTextAlign(html) : undefined
+
+  const borders = raw.borders || (tableEl as any)?.borders || undefined
+  const borderTop = getTableBorderStyle(borders?.top)
+  const borderRight = getTableBorderStyle(borders?.right)
+  const borderBottom = getTableBorderStyle(borders?.bottom)
+  const borderLeft = getTableBorderStyle(borders?.left)
+
+  const style: CSSProperties = {
+    padding: "2px 4px",
+    verticalAlign: "middle",
+    background,
+    color,
+    fontWeight,
+    fontStyle,
+    textAlign: textAlign as any,
+    borderTop: borderTop || undefined,
+    borderRight: borderRight || undefined,
+    borderBottom: borderBottom || undefined,
+    borderLeft: borderLeft || undefined,
+    overflow: "hidden",
+  }
+
+  return {
+    html,
+    colspan,
+    rowspan,
+    skip,
+    style,
+  }
+}
+
+type BorderInfo = {
+  color: string
+  width: number
+  dasharray?: string
+}
+
+function getBorderInfo(el: PptxElement): BorderInfo {
+  const directColor = String(el.borderColor ?? el.stroke ?? el.lineColor ?? "")
+  const directWidth = getNumber(el.borderWidth ?? el.strokeWidth ?? el.lineWidth)
+  const directDash = String(el.borderStrokeDasharray ?? el.strokeDasharray ?? el.dasharray ?? "")
+
+  const borderObj = el.border && typeof el.border === "object" ? el.border : null
+  const lineObj = el.line && typeof el.line === "object" ? el.line : null
+  const fallbackColor = String(borderObj?.color ?? lineObj?.color ?? "")
+  const fallbackWidth = getNumber(borderObj?.width ?? lineObj?.width)
+  const fallbackDash = String(borderObj?.dasharray ?? lineObj?.dasharray ?? "")
+
+  const color = directColor || fallbackColor
+  const width = directWidth || fallbackWidth
+  const dasharray = (directDash && directDash !== "0" ? directDash : "") || (fallbackDash && fallbackDash !== "0" ? fallbackDash : "")
+  return {
+    color: color || "transparent",
+    width: Math.max(0, width),
+    dasharray: dasharray || undefined,
+  }
+}
+
+type PatternShape =
+  | { kind: "circle"; cx: number; cy: number; r: number; fill: string }
+  | { kind: "polygon"; points: string; fill: string }
+  | { kind: "rect"; x: number; y: number; width: number; height: number; fill: string; transform?: string }
+
+type ShapePattern = {
+  id: string
+  width: number
+  height: number
+  background: string
+  shapes: PatternShape[]
+}
+
+type GradientStop = {
+  offset: string
+  color: string
+  opacity?: number
+}
+
+type ShapeGradient = {
+  id: string
+  kind: "linear" | "radial"
+  x1?: string
+  y1?: string
+  x2?: string
+  y2?: string
+  stops: GradientStop[]
+}
+
+type ShapeImagePaint = {
+  id: string
+  href: string
+}
+
+function toDomId(raw: string) {
+  return raw.replace(/[^a-zA-Z0-9_-]/g, "_")
+}
+
+function getShapePattern(el: PptxElement, slideIndex: number, cacheId: string): ShapePattern | null {
+  const fill = typeof el.fill === "object" ? (el.fill as PptxFill) : null
+  if (!fill || fill.type !== "pattern" || !fill.value) return null
+
+  const type = String(fill.value?.type || "")
+  const foreground = String(fill.value?.foregroundColor || "#000")
+  const background = String(fill.value?.backgroundColor || "#fff")
+  const id = `pptx-pattern-${slideIndex}-${toDomId(cacheId)}`
+
+  if (type === "pct5") {
+    return {
+      id,
+      width: 10,
+      height: 10,
+      background,
+      shapes: [{ kind: "circle", cx: 5, cy: 5, r: 1.2, fill: foreground }],
     }
   }
 
-  // 处理每个顶层元素
-  elements.forEach((element, index) => {
-    processElement(element, slideIndex + index + 2)
-  })
+  if (type === "solidDmnd") {
+    return {
+      id,
+      width: 12,
+      height: 12,
+      background,
+      shapes: [
+        {
+          kind: "polygon",
+          points: "6,0 12,6 6,12 0,6",
+          fill: foreground,
+        },
+      ],
+    }
+  }
+
+  return {
+    id,
+    width: 10,
+    height: 10,
+    background,
+    shapes: [{ kind: "circle", cx: 5, cy: 5, r: 1, fill: foreground }],
+  }
 }
 
-// 监听 pptxJson 变化
-watch(
-  () => props.pptxJson,
-  (newVal) => {
-    if (newVal) {
-      renderSlides()
+function getShapeImagePaint(el: PptxElement, slideIndex: number, cacheId: string): ShapeImagePaint | null {
+  const fill = typeof el.fill === "object" ? (el.fill as PptxFill) : null
+  if (!fill || fill.type !== "image") return null
+  const href = String(fill.value?.picBase64 || fill.value?.src || "")
+  if (!href) return null
+  return {
+    id: `pptx-shape-img-${slideIndex}-${toDomId(cacheId)}`,
+    href,
+  }
+}
+
+const shapeCache = {
+  pattern: new Map<string, ShapePattern | null>(),
+  image: new Map<string, ShapeImagePaint | null>(),
+  gradient: new Map<string, ShapeGradient | null>(),
+}
+
+function getCacheKey(slideIndex: number, cacheId: string) {
+  return `${slideIndex}-${cacheId}`
+}
+
+function getShapePatternCached(el: PptxElement, slideIndex: number, cacheId: string) {
+  const key = `p-${getCacheKey(slideIndex, cacheId)}`
+  if (shapeCache.pattern.has(key)) return shapeCache.pattern.get(key) as ShapePattern | null
+  const value = getShapePattern(el, slideIndex, cacheId)
+  shapeCache.pattern.set(key, value)
+  return value
+}
+
+function getShapeImagePaintCached(el: PptxElement, slideIndex: number, cacheId: string) {
+  const key = `i-${getCacheKey(slideIndex, cacheId)}`
+  if (shapeCache.image.has(key)) return shapeCache.image.get(key) as ShapeImagePaint | null
+  const value = getShapeImagePaint(el, slideIndex, cacheId)
+  shapeCache.image.set(key, value)
+  return value
+}
+
+function normalizeOffset(pos: unknown) {
+  const s = String(pos ?? "").trim()
+  if (!s) return ""
+  if (s.endsWith("%")) return s
+  const n = Number(s)
+  if (Number.isFinite(n)) return `${n}%`
+  return s
+}
+
+function getShapeGradient(el: PptxElement, slideIndex: number, cacheId: string): ShapeGradient | null {
+  const key = `g-${getCacheKey(slideIndex, cacheId)}`
+  if (shapeCache.gradient.has(key)) return shapeCache.gradient.get(key) as ShapeGradient | null
+
+  const fill = typeof el.fill === "object" ? (el.fill as PptxFill) : null
+  if (!fill || fill.type !== "gradient" || !fill.value) {
+    shapeCache.gradient.set(key, null)
+    return null
+  }
+
+  const colors = Array.isArray(fill.value?.colors) ? fill.value.colors : []
+  const rot = getNumber(fill.value?.rot)
+  const path = String(fill.value?.path || "rect")
+  const stops: GradientStop[] = colors
+    .map((c: any) => {
+      const offset = normalizeOffset(c?.pos)
+      const color = String(c?.color ?? "").trim()
+      const opacityRaw = c?.alpha ?? c?.opacity
+      const opacity = opacityRaw == null ? undefined : Math.max(0, Math.min(1, getNumber(opacityRaw)))
+      if (!color) return null
+      return {
+        offset: offset || undefined,
+        color,
+        opacity,
+      }
+    })
+    .filter(Boolean) as any
+
+  const id = `pptx-grad-${slideIndex}-${toDomId(cacheId)}`
+  if (!stops.length) {
+    shapeCache.gradient.set(key, null)
+    return null
+  }
+
+  if (path !== "rect") {
+    const result: ShapeGradient = {
+      id,
+      kind: "radial",
+      stops: stops.map((s) => ({ ...s, offset: s.offset || "0%" })),
     }
-  },
-  { deep: true }
-)
+    shapeCache.gradient.set(key, result)
+    return result
+  }
 
-// 组件挂载时渲染幻灯片
-onMounted(() => {
-  renderSlides()
-})
+  const angle = ((90 - rot + 360) % 360) * (Math.PI / 180)
+  const dx = Math.cos(angle)
+  const dy = Math.sin(angle)
+  const x1 = 0.5 - dx / 2
+  const y1 = 0.5 + dy / 2
+  const x2 = 0.5 + dx / 2
+  const y2 = 0.5 - dy / 2
+
+  const result: ShapeGradient = {
+    id,
+    kind: "linear",
+    x1: `${Math.max(0, Math.min(1, x1)) * 100}%`,
+    y1: `${Math.max(0, Math.min(1, y1)) * 100}%`,
+    x2: `${Math.max(0, Math.min(1, x2)) * 100}%`,
+    y2: `${Math.max(0, Math.min(1, y2)) * 100}%`,
+    stops: stops.map((s) => ({ ...s, offset: s.offset || "0%" })),
+  }
+  shapeCache.gradient.set(key, result)
+  return result
+}
+
+function hasShapeDefs(el: PptxElement, slideIndex: number, cacheId: string) {
+  return !!(
+    getShapeGradient(el, slideIndex, cacheId) ||
+    getShapePatternCached(el, slideIndex, cacheId) ||
+    getShapeImagePaintCached(el, slideIndex, cacheId)
+  )
+}
+
+function getShapeFill(el: PptxElement, slideIndex: number, cacheId: string) {
+  const fill = typeof el.fill === "object" ? (el.fill as PptxFill) : null
+  if (!fill || !fill.type) return "transparent"
+  if (fill.type === "color") return String(fill.value || "transparent")
+  if (fill.type === "gradient") {
+    const grad = getShapeGradient(el, slideIndex, cacheId)
+    return grad ? `url(#${grad.id})` : "transparent"
+  }
+  if (fill.type === "pattern") {
+    const pattern = getShapePatternCached(el, slideIndex, cacheId)
+    return pattern ? `url(#${pattern.id})` : String(fill.value?.foregroundColor || "transparent")
+  }
+  if (fill.type === "image") {
+    const paint = getShapeImagePaintCached(el, slideIndex, cacheId)
+    return paint ? `url(#${paint.id})` : "transparent"
+  }
+  return "transparent"
+}
+
+function getShapeStroke(el: PptxElement) {
+  const border = getBorderInfo(el)
+  return border.color || "transparent"
+}
+
+function getShapeStrokeWidth(el: PptxElement) {
+  const border = getBorderInfo(el)
+  return Math.max(0, border.width)
+}
+
+function getShapeDasharray(el: PptxElement) {
+  const border = getBorderInfo(el)
+  return border.dasharray
+}
+
+function getShapePath(el: PptxElement) {
+  const raw = typeof el.path === "string" ? el.path.trim() : ""
+  if (raw) return raw
+
+  const w = Math.max(0, getNumber(el.width))
+  const h = Math.max(0, getNumber(el.height))
+  if (!w || !h) return ""
+
+  const shapeType = String(el.shapType || el.shapeType || el.geom || "").toLowerCase()
+
+  if (shapeType === "ellipse" || shapeType === "circle") {
+    const cx = w / 2
+    const cy = h / 2
+    const rx = w / 2
+    const ry = h / 2
+    return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy} Z`
+  }
+
+  if (shapeType === "triangle" || shapeType === "tri") {
+    return `M ${w / 2} 0 L ${w} ${h} L 0 ${h} Z`
+  }
+
+  if (shapeType === "diamond" || shapeType === "rhombus") {
+    return `M ${w / 2} 0 L ${w} ${h / 2} L ${w / 2} ${h} L 0 ${h / 2} Z`
+  }
+
+  const r = Math.max(0, Math.min(Math.min(w, h) / 2, getNumber(el.radius || el.cornerRadius || el.rx)))
+  if (r) {
+    const rr = Math.min(r, w / 2, h / 2)
+    return `M ${rr} 0 H ${w - rr} A ${rr} ${rr} 0 0 1 ${w} ${rr} V ${h - rr} A ${rr} ${rr} 0 0 1 ${w - rr} ${h} H ${rr} A ${rr} ${rr} 0 0 1 0 ${h - rr} V ${rr} A ${rr} ${rr} 0 0 1 ${rr} 0 Z`
+  }
+
+  return `M 0 0 H ${w} V ${h} H 0 Z`
+}
 </script>
 
-<style scoped>
-.pptx-container {
+<style scoped lang="less">
+.pptx-preview {
+  width: 100%;
+}
+
+.pptx-empty {
+  padding: 40px 12px;
+  color: #909399;
+  text-align: center;
+}
+
+.pptx-slides {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+  align-items: center;
+}
+
+.pptx-slide-shell {
+  position: relative;
+  display: flex;
+  align-items: flex-start;
+  justify-content: center;
+}
+
+.pptx-slide {
+  position: absolute;
+  left: 0;
+  top: 0;
+  transform-origin: top left;
+  border-radius: 6px;
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
+  overflow: hidden;
+}
+
+.pptx-element {
+  overflow: visible;
+}
+
+.pptx-img,
+.pptx-media {
+  width: 100%;
+  height: 100%;
+}
+
+.pptx-media {
+  object-fit: contain;
+}
+
+.pptx-shape-svg {
+  width: 100%;
+  height: 100%;
+  display: block;
+}
+
+.pptx-chart {
   width: 100%;
-  overflow-x: auto;
-  padding: 20px 0;
+  height: 100%;
+  display: block;
+}
+
+.pptx-group-inner {
+  width: 100%;
+  height: 100%;
+  position: relative;
+}
+
+.pptx-table-wrap {
+  width: 100%;
+  height: 100%;
+}
+
+.pptx-table {
+  width: 100%;
+  height: 100%;
+  table-layout: fixed;
+  border-collapse: collapse;
+}
+
+.pptx-table-html {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  pointer-events: none;
+}
+
+.pptx-html {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  pointer-events: none;
+}
+
+.pptx-html :deep(p) {
+  margin: 0;
+  padding: 0;
+  word-break: break-word;
+}
+
+.pptx-html :deep(ul),
+.pptx-html :deep(ol) {
+  margin: 0;
+  padding: 0 0 0 20px;
+  word-break: break-word;
+}
+
+.pptx-table-html :deep(p) {
+  margin: 0;
+  padding: 0;
+  word-break: break-word;
+}
+
+.pptx-table-html :deep(ul),
+.pptx-table-html :deep(ol) {
+  margin: 0;
+  padding: 0 0 0 20px;
+  word-break: break-word;
 }
 </style>

+ 0 - 18
src/components/view_file/vendors/pptx/elements/audio.js

@@ -1,18 +0,0 @@
-/*
- * @Author: LiZhiWei
- * @Date: 2025-05-14 15:22:27
- * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-14 15:22:38
- * @Description:
- */
-export function createAudioElement (element) {
-  const el = document.createElement('audio')
-  el.src = element.blob
-  el.controls = true
-  el.style.height = element.height + 'px'
-  el.style.position = 'absolute'
-  el.style.top = element.top + 'px'
-  el.style.left = element.left + 'px'
-  el.style.zIndex = element.order
-  return el
-}

+ 0 - 294
src/components/view_file/vendors/pptx/elements/chart.js

@@ -1,294 +0,0 @@
-/*
- * @Author: LiZhiWei
- * @Date: 2025-05-14 15:46:50
- * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-14 15:50:02
- * @Description:
- */
-// 创建图表元素
-export function createChartElement (element) {
-  // 1. 创建基础容器
-  const el = document.createElement('div')
-  el.style.position = 'absolute'
-  el.style.top = element.top + 'px'
-  el.style.left = element.left + 'px'
-  el.style.width = element.width + 'px'
-  el.style.height = element.height + 'px'
-  el.style.zIndex = element.order
-  // 2. 创建SVG画布
-  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
-  svg.setAttribute('width', element.width)
-  svg.setAttribute('height', element.height)
-  svg.setAttribute('viewBox', `0 0 ${element.width} ${element.height}`)
-
-  // 3. 设置图表内边距
-  const padding = {
-    top: 60, // 为图例留出空间
-    right: 40, // 右侧边距
-    bottom: 60, // X轴标签空间
-    left: 60 // Y轴标签空间
-  }
-
-  // 4. 计算实际绘图区域
-  const chartWidth = element.width - padding.left - padding.right
-  const chartHeight = element.height - padding.top - padding.bottom
-  // 处理不同图表类型
-  switch (element.chartType) {
-    case 'barChart':
-      // 绘制柱状图
-      drawBarChart(svg, element, {
-        padding,
-        chartWidth,
-        chartHeight,
-        barDir: element.barDir || 'col',
-        grouping: element.grouping || 'clustered'
-      })
-      break
-    case 'pieChart':
-    case 'doughnutChart':
-      drawDonutChart(svg, element, chartWidth, chartHeight)
-      break
-    default:
-      console.warn('Unsupported chart type:', element.chartType)
-  }
-
-  el.appendChild(svg)
-  return el
-}
-
-export function drawDonutChart (svg, element, chartWidth, chartHeight) {
-  // 计算饼图中心点和半径
-  const cx = element.width / 2
-  const cy = element.height / 2
-  const radius = Math.min(chartWidth, chartHeight) / 2
-
-  // 计算所有数据总和
-  const total = element.data[0].values.reduce((sum, item) => sum + item.y, 0)
-
-  // 创建颜色数组
-  const colors = element.colors || ['#5B9BD5', '#ED7D31', '#A5A5A5', '#FFC000']
-
-  let startAngle = 0
-  element.data[0].values.forEach((item, index) => {
-    // 计算扇形角度
-    const angle = (item.y / total) * Math.PI * 2
-
-    // 计算扇形路径
-    const endAngle = startAngle + angle
-    const x1 = cx + radius * Math.cos(startAngle)
-    const y1 = cy + radius * Math.sin(startAngle)
-    const x2 = cx + radius * Math.cos(endAngle)
-    const y2 = cy + radius * Math.sin(endAngle)
-
-    // 创建扇形路径
-    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
-    const largeArcFlag = angle > Math.PI ? 1 : 0
-
-    // 根据是否为环形图决定内圆半径
-    const innerRadius = element.chartType === 'doughnutChart' ? radius * 0.6 : 0
-    if (element.chartType === 'doughnutChart') {
-      // 环形图路径
-      const ix1 = cx + innerRadius * Math.cos(startAngle)
-      const iy1 = cy + innerRadius * Math.sin(startAngle)
-      const ix2 = cx + innerRadius * Math.cos(endAngle)
-      const iy2 = cy + innerRadius * Math.sin(endAngle)
-
-      path.setAttribute(
-        'd',
-        `
-          M ${x1} ${y1}
-          A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}
-          L ${ix2} ${iy2}
-          A ${innerRadius} ${innerRadius} 0 ${largeArcFlag} 0 ${ix1} ${iy1}
-          Z
-        `
-      )
-    } else {
-      // 饼图路径
-      path.setAttribute(
-        'd',
-        `
-          M ${cx} ${cy}
-          L ${x1} ${y1}
-          A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}
-          Z
-        `
-      )
-    }
-
-    // 设置填充色
-    path.setAttribute('fill', colors[index % colors.length])
-    path.setAttribute('stroke', '#fff')
-    path.setAttribute('stroke-width', '1')
-    svg.appendChild(path)
-
-    // 添加数值标签
-    const labelAngle = startAngle + angle / 2
-    const labelRadius = radius * 1.1
-    const labelX = cx + labelRadius * Math.cos(labelAngle)
-    const labelY = cy + labelRadius * Math.sin(labelAngle)
-
-    const label = document.createElementNS('http://www.w3.org/2000/svg', 'text')
-    label.setAttribute('x', labelX)
-    label.setAttribute('y', labelY)
-    label.setAttribute('text-anchor', 'middle')
-    label.setAttribute('alignment-baseline', 'middle')
-    label.setAttribute('font-size', '12px')
-    label.textContent = `${((item.y / total) * 100).toFixed(1)}%`
-    svg.appendChild(label)
-
-    startAngle = endAngle
-  })
-}
-// 绘制柱状图
-export function drawBarChart (svg, element, options) {
-  const { padding, chartWidth, chartHeight, barDir, grouping } = options
-  const series = element.data
-  const categories = series[0].xlabels
-  const categoryCount = Object.keys(categories).length
-
-  // 1. 计算最大值
-  let maxValue = 0
-  series.forEach((serie) => {
-    const seriesMax = Math.max(...serie.values.map((v) => v.y))
-    maxValue = Math.max(maxValue, seriesMax)
-  })
-  maxValue = maxValue * 1.2 // 增加20%空间
-
-  // 2. 计算柱子布局
-  const groupWidth = chartWidth / categoryCount
-  const barWidth =
-      grouping === 'clustered'
-        ? (groupWidth * 0.6) / series.length // 分组模式
-        : groupWidth * 0.6 // 堆叠模式
-  const barSpacing = (groupWidth * 0.4) / (grouping === 'clustered' ? series.length + 1 : 2)
-
-  // 3. 绘制坐标轴
-  // X轴
-  const xAxisPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')
-  xAxisPath.setAttribute(
-    'd',
-    `M${padding.left},${element.height - padding.bottom} L${element.width - padding.right},${
-      element.height - padding.bottom
-    }`
-  )
-  xAxisPath.setAttribute('stroke', '#000')
-  xAxisPath.setAttribute('stroke-width', '1')
-  svg.appendChild(xAxisPath)
-
-  // Y轴
-  const yAxisPath = document.createElementNS('http://www.w3.org/2000/svg', 'path')
-  yAxisPath.setAttribute(
-    'd',
-    `M${padding.left},${padding.top} L${padding.left},${element.height - padding.bottom}`
-  )
-  yAxisPath.setAttribute('stroke', '#000')
-  yAxisPath.setAttribute('stroke-width', '1')
-  svg.appendChild(yAxisPath)
-
-  // 4. 绘制Y轴刻度和网格线
-  const yTickCount = 5
-  for (let i = 0; i <= yTickCount; i++) {
-    const y = padding.top + (chartHeight * i) / yTickCount
-    const value = maxValue - (maxValue * i) / yTickCount
-
-    // 水平网格线
-    const gridLine = document.createElementNS('http://www.w3.org/2000/svg', 'line')
-    gridLine.setAttribute('x1', padding.left)
-    gridLine.setAttribute('y1', y)
-    gridLine.setAttribute('x2', padding.left + chartWidth)
-    gridLine.setAttribute('y2', y)
-    gridLine.setAttribute('stroke', '#eee')
-    gridLine.setAttribute('stroke-width', '1')
-    svg.appendChild(gridLine)
-
-    // 刻度线
-    const tick = document.createElementNS('http://www.w3.org/2000/svg', 'line')
-    tick.setAttribute('x1', padding.left - 6)
-    tick.setAttribute('y1', y)
-    tick.setAttribute('x2', padding.left)
-    tick.setAttribute('y2', y)
-    tick.setAttribute('stroke', '#000')
-    tick.setAttribute('stroke-width', '1')
-    svg.appendChild(tick)
-
-    // 刻度值
-    const label = document.createElementNS('http://www.w3.org/2000/svg', 'text')
-    label.setAttribute('x', padding.left - 10)
-    label.setAttribute('y', y + 4)
-    label.setAttribute('text-anchor', 'end')
-    label.setAttribute('font-size', '12px')
-    label.textContent = value.toFixed(1)
-    svg.appendChild(label)
-  }
-
-  // 5. 绘制数据条
-  series.forEach((serie, serieIndex) => {
-    serie.values.forEach((value, index) => {
-      const barHeight = (value.y / maxValue) * chartHeight
-      const x =
-          padding.left +
-          groupWidth * index +
-          (grouping === 'clustered'
-            ? barSpacing * (serieIndex + 1) + barWidth * serieIndex
-            : barSpacing)
-      const y = element.height - padding.bottom - barHeight
-
-      // 绘制柱子
-      const bar = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
-      bar.setAttribute('x', x)
-      bar.setAttribute('y', y)
-      bar.setAttribute('width', barWidth)
-      bar.setAttribute('height', barHeight)
-      bar.setAttribute(
-        'fill',
-        element.colors[serieIndex] || `hsl(${serieIndex * 60}, 70%, 50%)`
-      )
-      svg.appendChild(bar)
-
-      // 数值标签
-      if (element.marker) {
-        const label = document.createElementNS('http://www.w3.org/2000/svg', 'text')
-        label.setAttribute('x', x + barWidth / 2)
-        label.setAttribute('y', y - 5)
-        label.setAttribute('text-anchor', 'middle')
-        label.setAttribute('font-size', '12px')
-        label.textContent = value.y.toFixed(1)
-        svg.appendChild(label)
-      }
-    })
-  })
-
-  // 6. 绘制X轴类别标签
-  Object.values(categories).forEach((label, index) => {
-    const x = padding.left + groupWidth * (index + 0.5)
-    const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
-    text.setAttribute('x', x)
-    text.setAttribute('y', element.height - padding.bottom + 20)
-    text.setAttribute('text-anchor', 'middle')
-    text.setAttribute('font-size', '12px')
-    text.textContent = label
-    svg.appendChild(text)
-  })
-
-  // 7. 绘制图例
-  series.forEach((serie, index) => {
-    const legendX = padding.left + index * 120
-    const legendY = 20
-
-    const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
-    rect.setAttribute('x', legendX)
-    rect.setAttribute('y', legendY)
-    rect.setAttribute('width', 15)
-    rect.setAttribute('height', 15)
-    rect.setAttribute('fill', element.colors[index] || `hsl(${index * 60}, 70%, 50%)`)
-    svg.appendChild(rect)
-
-    const text = document.createElementNS('http://www.w3.org/2000/svg', 'text')
-    text.setAttribute('x', legendX + 25)
-    text.setAttribute('y', legendY + 12)
-    text.setAttribute('font-size', '12px')
-    text.textContent = serie.key
-    svg.appendChild(text)
-  })
-}

+ 0 - 13
src/components/view_file/vendors/pptx/elements/image.js

@@ -1,13 +0,0 @@
-export function createImageElement (element) {
-  const img = document.createElement('img')
-  img.src = element.src
-  img.style.width = element.width + 'px'
-  img.style.height = element.height + 'px'
-  img.style.objectFit = 'cover' // 保持图像的宽高比并填充容器
-  img.style.position = 'absolute'
-  img.style.top = `${element.top}px`
-  img.style.left = `${element.left}px`
-  img.style.zIndex = element.order
-
-  return img
-}

+ 0 - 51
src/components/view_file/vendors/pptx/elements/math.js

@@ -1,51 +0,0 @@
-/*
- * @Author: LiZhiWei
- * @Date: 2025-05-14 15:52:16
- * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-14 15:52:19
- * @Description:
- */
-// 创建数学公式元素
-export function createMathElement (element) {
-  const el = document.createElement('div')
-  el.style.position = 'absolute'
-  el.style.top = element.top + 'px'
-  el.style.left = element.left + 'px'
-  el.style.width = element.width + 'px'
-  el.style.height = element.height + 'px'
-
-  // 如果有公式图片,优先使用图片显示
-  if (element.picBase64) {
-    const img = document.createElement('img')
-    img.src = element.picBase64
-    img.style.width = '100%'
-    img.style.height = '100%'
-    img.style.objectFit = 'contain'
-    el.appendChild(img)
-    return el
-  }
-
-  // 如果有 LaTeX 表达式,使用 MathJax 渲染
-  if (element.latex) {
-    // 创建公式容器
-    const mathContainer = document.createElement('div')
-    mathContainer.style.width = '100%'
-    mathContainer.style.height = '100%'
-    mathContainer.style.display = 'flex'
-    mathContainer.style.alignItems = 'center'
-    mathContainer.style.justifyContent = 'center'
-
-    // 添加 LaTeX 公式
-    mathContainer.innerHTML = `\\[${element.latex}\\]`
-
-    // 如果 MathJax 不可用,显示原始 LaTeX
-    mathContainer.style.fontFamily = 'monospace'
-    mathContainer.style.whiteSpace = 'pre-wrap'
-    mathContainer.style.padding = '10px'
-    mathContainer.textContent = element.latex
-
-    el.appendChild(mathContainer)
-  }
-
-  return el
-}

+ 0 - 3814
src/components/view_file/vendors/pptx/elements/shape.js

@@ -1,3814 +0,0 @@
-import { adjustBrightness, convertPtToPxInContent } from "../utils/style"
-export function createShapeElement(element) {
-  const el = document.createElement("div")
-  el.style.position = "absolute"
-  el.style.top = element.top + "px"
-  el.style.left = element.left + "px"
-  el.style.width = element.width + "px"
-  el.style.height = element.height + "px"
-  el.style.zIndex = element.order
-  el.style.overflow = "visible"
-  if (element.height === 0) {
-    // 如果高度为0,直接在div上绘制边框
-    el.style.borderTop = `${element.borderWidth || 1}px ${
-      element.borderType || "solid"
-    } ${element.borderColor || "#000"}`
-  }
-  // 使用SVG绘制形状
-  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg")
-  svg.setAttribute("width", "100%")
-  svg.setAttribute("height", "100%")
-  svg.setAttribute("viewBox", `0 0 ${element.width} ${element.height}`)
-  svg.style.overflow = "visible"
-  const setBackground = (element, shape) => {
-    if (element.fill && element.fill.type) {
-      // 设置填充色
-      if (element.fill.type === "color") {
-        shape.setAttribute("fill", element.fill.value || "transparent")
-      } else if (element.fill.type === "gradient") {
-        // 渐变填充
-        const { colors, path, rot } = element.fill.value
-
-        if (colors && colors.length >= 2) {
-          const gradientType = path === "rect" ? "linear" : "radial"
-          const gradientAngle =
-            gradientType === "linear" ? (90 - (rot || 0)) % 360 : rot || 0
-
-          let gradientString = `${gradientType}-gradient(`
-          if (gradientType === "linear") {
-            gradientString += `${gradientAngle}deg, `
-          }
-
-          colors.forEach((color, i) => {
-            gradientString += `${color.color} ${color.pos}${
-              i < colors.length - 1 ? ", " : ""
-            }`
-          })
-          gradientString += ")"
-
-          // 创建渐变定义
-          const gradientDef = document.createElementNS(
-            "http://www.w3.org/2000/svg",
-            "defs"
-          )
-          const gradientEl = document.createElementNS(
-            "http://www.w3.org/2000/svg",
-            gradientType === "linear" ? "linearGradient" : "radialGradient"
-          )
-          const gradientId = `gradient-${Date.now()}-${Math.random()
-            .toString(36)
-            .substr(2, 9)}`
-          gradientEl.setAttribute("id", gradientId)
-
-          // 设置渐变属性
-          if (gradientType === "linear") {
-            gradientEl.setAttribute(
-              "gradientTransform",
-              `rotate(${gradientAngle})`
-            )
-          }
-
-          // 添加渐变色标
-          colors.forEach((color) => {
-            const stop = document.createElementNS(
-              "http://www.w3.org/2000/svg",
-              "stop"
-            )
-            stop.setAttribute("offset", color.pos)
-            stop.setAttribute("stop-color", color.color)
-            gradientEl.appendChild(stop)
-          })
-
-          gradientDef.appendChild(gradientEl)
-          svg.appendChild(gradientDef)
-
-          // 应用渐变
-          shape.setAttribute("fill", `url(#${gradientId})`)
-        }
-      } else if (element.fill.type === "image") {
-        // 创建图案填充
-        const pattern = document.createElementNS(
-          "http://www.w3.org/2000/svg",
-          "pattern"
-        )
-        const patternId = `pattern-${Date.now()}-${Math.random()
-          .toString(36)
-          .substr(2, 9)}`
-        pattern.setAttribute("id", patternId)
-        pattern.setAttribute("patternUnits", "userSpaceOnUse")
-        pattern.setAttribute("width", "100%")
-        pattern.setAttribute("height", "100%")
-
-        // 创建图片元素
-        const image = document.createElementNS(
-          "http://www.w3.org/2000/svg",
-          "image"
-        )
-        image.setAttribute("width", "100%")
-        image.setAttribute("height", "100%")
-        image.setAttribute("preserveAspectRatio", "xMidYMid slice")
-        image.setAttributeNS(
-          "http://www.w3.org/1999/xlink",
-          "href",
-          element.fill.value.picBase64
-        )
-
-        pattern.appendChild(image)
-
-        // 添加pattern到defs
-        const defs = document.createElementNS(
-          "http://www.w3.org/2000/svg",
-          "defs"
-        )
-        defs.appendChild(pattern)
-        svg.appendChild(defs)
-
-        // 应用图案填充
-        shape.setAttribute("fill", `url(#${patternId})`)
-      } else {
-        shape.setAttribute("fill", "transparent")
-      }
-    } else {
-      shape.setAttribute("fill", "#ffffff00")
-    }
-  }
-  // 根据形状类型创建不同的SVG元素
-  switch (element.shapType) {
-    case "roundRect":
-      const radius = Math.min(element.width, element.height) * 0.1
-      const roundRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "rect"
-      )
-      roundRect.setAttribute("x", 0)
-      roundRect.setAttribute("y", 0)
-      roundRect.setAttribute("width", element.width)
-      roundRect.setAttribute("height", element.height)
-      roundRect.setAttribute("rx", radius)
-      roundRect.setAttribute("ry", radius)
-
-      // 设置填充色
-      setBackground(element, roundRect)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        roundRect.setAttribute("stroke", element.borderColor || "#000")
-        roundRect.setAttribute("stroke-width", element.borderWidth || 1)
-        roundRect.setAttribute("stroke-linejoin", "round") // 设置连接处为圆角
-        roundRect.setAttribute("vector-effect", "non-scaling-stroke") // 防止边框宽度变形
-        roundRect.setAttribute("shape-rendering", "geometricPrecision") // 提高渲染精度
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            roundRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            roundRect.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            roundRect.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(roundRect)
-      break
-    case "snip1Rect":
-      // 使用path元素绘制剪去单角的矩形
-      const snip1Rect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算剪角的大小,通常为矩形较短边的20%
-      const snipSize = Math.min(element.width, element.height) * 0.35
-
-      // 绘制路径:从左上角开始,顺时针方向,右上角被剪去
-      snip1Rect.setAttribute(
-        "d",
-        `M0,0 ` +
-          `L${element.width - snipSize},0 ` +
-          `L${element.width},${snipSize} ` +
-          `L${element.width},${element.height} ` +
-          `L0,${element.height} ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, snip1Rect)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        snip1Rect.setAttribute("stroke", element.borderColor || "#000")
-        snip1Rect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            snip1Rect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            snip1Rect.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            snip1Rect.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-      svg.appendChild(snip1Rect)
-      break
-    case "snip2SameRect":
-      // 使用path元素绘制剪去四个角的矩形
-      const snip2SameRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算剪角的大小,通常为矩形较短边的20%
-      const snip2Size = Math.min(element.width, element.height) * 0.35
-
-      // 绘制路径:从左上角开始,顺时针方向,剪去四个角
-      snip2SameRect.setAttribute(
-        "d",
-        `M${snip2Size},0 ` +
-          `L${element.width - snip2Size},0 ` +
-          `L${element.width},${snip2Size} ` +
-          `L${element.width},${element.height - snip2Size} ` +
-          `L${element.width - snip2Size},${element.height} ` +
-          `L${snip2Size},${element.height} ` +
-          `L0,${element.height - snip2Size} ` +
-          `L0,${snip2Size} ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, snip2SameRect)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        snip2SameRect.setAttribute("stroke", element.borderColor || "#000")
-        snip2SameRect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            snip2SameRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            snip2SameRect.setAttribute("stroke-dasharray", "2, 2")
-            snip2SameRect.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            snip2SameRect.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        // 添加这些属性以确保边框正确渲染
-        snip2SameRect.setAttribute("vector-effect", "non-scaling-stroke")
-        snip2SameRect.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(snip2SameRect)
-      break
-    case "line":
-      // 创建直线连接符
-      const line = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "line"
-      )
-      // 设置SVG的最小高度为1px
-      const svgHeight = element.height > 0 ? element.height : 1
-      svg.setAttribute("height", svgHeight + "px")
-
-      // 设置线条的起点和终点
-      line.setAttribute("x1", 0)
-      line.setAttribute("y1", 0)
-      line.setAttribute("x2", element.width)
-      line.setAttribute("y2", svgHeight)
-
-      // 确保边框颜色和宽度被正确设置
-      line.setAttribute("stroke", element.borderColor || "#000")
-      line.setAttribute("stroke-width", element.borderWidth || 1)
-
-      // 处理虚线样式
-      if (element.borderType === "dotted" || element.borderType === "dashed") {
-        if (element.borderStrokeDasharray) {
-          line.setAttribute("stroke-dasharray", element.borderStrokeDasharray)
-        } else if (element.borderType === "dotted") {
-          line.setAttribute("stroke-dasharray", "2, 2")
-          line.setAttribute("stroke-linecap", "round") // 添加圆角端点使点线更明显
-        } else if (element.borderType === "dashed") {
-          line.setAttribute("stroke-dasharray", "6, 3")
-        }
-      }
-
-      // 确保线条正确渲染
-      line.setAttribute("vector-effect", "non-scaling-stroke") // 防止缩放影响线条宽度
-      svg.appendChild(line)
-      break
-    case "snip2DiagRect":
-      // 使用path元素绘制剪去右上角和左下角的矩形
-      const snip2DiagRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算剪角的大小,通常为矩形较短边的35%
-      const snipDiagSize = Math.min(element.width, element.height) * 0.35
-
-      // 绘制路径:从左上角开始,顺时针方向,右上角和左下角被剪去
-      snip2DiagRect.setAttribute(
-        "d",
-        `M0,0 ` +
-          `L${element.width - snipDiagSize},0 ` +
-          `L${element.width},${snipDiagSize} ` +
-          `L${element.width},${element.height} ` +
-          `L${snipDiagSize},${element.height} ` +
-          `L0,${element.height - snipDiagSize} ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, snip2DiagRect)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        snip2DiagRect.setAttribute("stroke", element.borderColor || "#000")
-        snip2DiagRect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            snip2DiagRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            snip2DiagRect.setAttribute("stroke-dasharray", "2, 2")
-            snip2DiagRect.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            snip2DiagRect.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        // 添加这些属性以确保边框正确渲染
-        snip2DiagRect.setAttribute("vector-effect", "non-scaling-stroke")
-        snip2DiagRect.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(snip2DiagRect)
-      break
-    case "snipRoundRect":
-      const snipRoundRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      // 计算剪切大小和圆角大小
-      const snipSize2 = Math.min(element.width, element.height) * 0.4
-      const roundSize = Math.min(element.width, element.height) * 0.5
-
-      // 绘制路径:从左上角开始,顺时针方向,左上为圆角,右上为剪切角
-      snipRoundRect.setAttribute(
-        "d",
-        `M${roundSize},0 ` +
-          `L${element.width - snipSize2},0 ` +
-          `L${element.width},${snipSize2} ` +
-          `L${element.width},${element.height} ` +
-          `L0,${element.height} ` +
-          `L0,${roundSize} ` +
-          `A${roundSize},${roundSize} 0 0,1 ${roundSize},0 ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, snipRoundRect)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        snipRoundRect.setAttribute("stroke", element.borderColor || "#000")
-        snipRoundRect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            snipRoundRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            snipRoundRect.setAttribute("stroke-dasharray", "2, 2")
-            snipRoundRect.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            snipRoundRect.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        snipRoundRect.setAttribute("vector-effect", "non-scaling-stroke")
-        snipRoundRect.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(snipRoundRect)
-      break
-    case "round1Rect":
-      const round1Rect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      // 计算圆角大小
-      const round1Size = Math.min(element.width, element.height) * 0.5
-
-      // 绘制路径:从左上角开始,顺时针方向,右上角为圆角
-      round1Rect.setAttribute(
-        "d",
-        `M0,0 ` +
-          `L${element.width - round1Size},0 ` +
-          `Q${element.width},0 ${element.width},${round1Size} ` +
-          `L${element.width},${element.height} ` +
-          `L0,${element.height} ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, round1Rect)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        round1Rect.setAttribute("stroke", element.borderColor || "#000")
-        round1Rect.setAttribute("stroke-width", element.borderWidth || 1)
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            round1Rect.setAttribute("stroke-dasharray", "40,15,5,15")
-          } else if (element.borderType === "dotted") {
-            round1Rect.setAttribute("stroke-dasharray", "2, 2")
-            round1Rect.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            round1Rect.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        round1Rect.setAttribute("vector-effect", "non-scaling-stroke")
-        round1Rect.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(round1Rect)
-      break
-    case "ellipse":
-    case "circle":
-      const ellipse = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "ellipse"
-      )
-      ellipse.setAttribute("cx", element.width / 2)
-      ellipse.setAttribute("cy", element.height / 2)
-      ellipse.setAttribute("rx", element.width / 2)
-      ellipse.setAttribute("ry", element.height / 2)
-
-      // 设置填充色
-      setBackground(element, ellipse)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        ellipse.setAttribute("stroke", element.borderColor || "#000")
-        ellipse.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            ellipse.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            ellipse.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            ellipse.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(ellipse)
-      break
-    case "round2SameRect":
-      const round2SameRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      // 计算圆角大小
-      const round2Size = Math.min(element.width, element.height) * 0.5
-
-      // 绘制路径:从左上角开始,顺时针方向,左上和右上为圆角
-      round2SameRect.setAttribute(
-        "d",
-        `M${round2Size},0 ` +
-          `L${element.width - round2Size},0 ` +
-          `Q${element.width},0 ${element.width},${round2Size} ` +
-          `L${element.width},${element.height} ` +
-          `L0,${element.height} ` +
-          `L0,${round2Size} ` +
-          `Q0,0 ${round2Size},0 ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, round2SameRect)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        round2SameRect.setAttribute("stroke", element.borderColor || "#000")
-        round2SameRect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            round2SameRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            round2SameRect.setAttribute("stroke-dasharray", "2, 2")
-            round2SameRect.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            round2SameRect.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        round2SameRect.setAttribute("vector-effect", "non-scaling-stroke")
-        round2SameRect.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(round2SameRect)
-      break
-    case "round2DiagRect":
-      const round2DiagRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      // 计算圆角大小
-      const round2DiagSize = Math.min(element.width, element.height) * 0.5
-
-      // 绘制路径:从左上角开始,顺时针方向,左上和右下为圆角
-      round2DiagRect.setAttribute(
-        "d",
-        `M${round2DiagSize},0 ` +
-          `L${element.width},0 ` +
-          `L${element.width},${element.height - round2DiagSize} ` +
-          `Q${element.width},${element.height} ${
-            element.width - round2DiagSize
-          },${element.height} ` +
-          `L0,${element.height} ` +
-          `L0,${round2DiagSize} ` +
-          `Q0,0 ${round2DiagSize},0 ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, round2DiagRect)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        round2DiagRect.setAttribute("stroke", element.borderColor || "#000")
-        round2DiagRect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            round2DiagRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            round2DiagRect.setAttribute("stroke-dasharray", "2, 2")
-            round2DiagRect.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            round2DiagRect.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        round2DiagRect.setAttribute("vector-effect", "non-scaling-stroke")
-        round2DiagRect.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(round2DiagRect)
-      break
-    case "triangle":
-      const triangle = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      triangle.setAttribute(
-        "points",
-        `${element.width / 2},0 ${element.width},${element.height} 0,${
-          element.height
-        }`
-      )
-
-      // 设置填充色
-      setBackground(element, triangle)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        triangle.setAttribute("stroke", element.borderColor || "#000")
-        triangle.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            triangle.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            triangle.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            triangle.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(triangle)
-      break
-    case "arc":
-      const arc = document.createElementNS("http://www.w3.org/2000/svg", "path")
-
-      // 计算弧形的参数
-      const arcRadius = Math.min(element.width, element.height) / 2
-
-      // 绘制弧形路径
-      arc.setAttribute(
-        "d",
-        `M${arcRadius},0 ` +
-          `A${arcRadius},${arcRadius} 0 1 1 ${arcRadius * 0.15},${
-            arcRadius * 0.5
-          }`
-      )
-
-      // 设置填充色
-      arc.setAttribute("fill", "transparent")
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        arc.setAttribute("stroke", element.borderColor || "#000")
-        arc.setAttribute("stroke-width", element.borderWidth || 0.5)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            arc.setAttribute("stroke-dasharray", element.borderStrokeDasharray)
-          } else if (element.borderType === "dotted") {
-            arc.setAttribute("stroke-dasharray", "2, 2")
-            arc.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            arc.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        arc.setAttribute("vector-effect", "non-scaling-stroke")
-        arc.setAttribute("shape-rendering", "geometricPrecision")
-      } else {
-        arc.setAttribute("stroke", element.borderColor || "#000")
-        arc.setAttribute("stroke-width", 0.5)
-      }
-
-      svg.appendChild(arc)
-      break
-    case "custom":
-      const customPath = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 直接使用传入的 path 数据
-      customPath.setAttribute("d", element.path || "")
-
-      // 设置填充色
-      setBackground(element, customPath)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        customPath.setAttribute("stroke", element.borderColor || "#000")
-        customPath.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            customPath.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            customPath.setAttribute("stroke-dasharray", "2, 2")
-            customPath.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            customPath.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        customPath.setAttribute("vector-effect", "non-scaling-stroke")
-        customPath.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(customPath)
-      break
-    case "teardrop":
-      const teardrop = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算泪珠形状的参数
-      const tdCenterX = element.width / 2
-      const tdCenterY = element.height / 2
-      const tdRadiusX = element.width / 2
-      const tdRadiusY = element.height / 2
-
-      // 使用相对比例计算控制点
-      teardrop.setAttribute(
-        "d",
-        `M${tdCenterX * 2} ${tdCenterY} ` +
-          `A ${tdRadiusX} ${tdRadiusY} 0 1 1 ${tdCenterX} 0 ` +
-          `Q${tdCenterX * 1.7},0 ${tdCenterX * 2.1},${-tdCenterY * 0.1} ` +
-          `Q${tdCenterX * 2},${tdCenterY * 0.29} ${tdCenterX * 2},${tdCenterY}`
-      )
-
-      // 设置填充色
-      setBackground(element, teardrop)
-
-      // 设置边框样式
-      if (element.borderWidth > 0) {
-        teardrop.setAttribute("stroke", element.borderColor || "#000")
-        teardrop.setAttribute("stroke-width", element.borderWidth || 1)
-        teardrop.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          // ... 原有的虚线边框处理代码 ...
-        }
-      }
-
-      svg.appendChild(teardrop)
-      break
-    case "decagon":
-      const decagon = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-
-      // 计算十边形的顶点
-      let decagonPoints = ""
-      for (let i = 0; i < 10; i++) {
-        const angle = (i * 2 * Math.PI) / 10 - Math.PI / 2 // 从顶部开始
-        const x = element.width / 2 + (element.width / 2) * Math.cos(angle)
-        const y = element.height / 2 + (element.height / 2) * Math.sin(angle)
-        decagonPoints += `${x},${y} `
-      }
-      decagon.setAttribute("points", decagonPoints.trim())
-
-      // 设置填充色
-      setBackground(element, decagon)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        decagon.setAttribute("stroke", element.borderColor || "#000")
-        decagon.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            decagon.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            decagon.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            decagon.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(decagon)
-      break
-    case "pentagon":
-      const pentagon = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      pentagon.setAttribute(
-        "points",
-        `${element.width / 2},0 ${element.width},${element.height * 0.38} ` +
-          `${element.width * 0.82},${element.height} ${element.width * 0.18},${
-            element.height
-          } ` +
-          `0,${element.height * 0.38}`
-      )
-
-      // 设置填充色
-      setBackground(element, pentagon)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        pentagon.setAttribute("stroke", element.borderColor || "#000")
-        pentagon.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            pentagon.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            pentagon.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            pentagon.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(pentagon)
-      break
-    case "pie":
-      const pie = document.createElementNS("http://www.w3.org/2000/svg", "path")
-
-      // 使用提供的路径数据,但保留元素的宽高比例
-      const centerX = element.width / 2
-      const centerY = element.height / 2
-      const radius2 = Math.min(element.width, element.height) / 2
-
-      // 绘制饼图,使用类似提供的路径数据
-      pie.setAttribute(
-        "d",
-        `M${centerX},${centerY} ` +
-          `L${centerX * 1.85},${centerY * 1.52} ` +
-          `A${radius2},${radius2} 0 1,1 ${centerX * 1.56},${centerY * 0.17} ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, pie)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        pie.setAttribute("stroke", element.borderColor || "#000")
-        pie.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            pie.setAttribute("stroke-dasharray", element.borderStrokeDasharray)
-          } else if (element.borderType === "dotted") {
-            pie.setAttribute("stroke-dasharray", "2, 2")
-            pie.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            pie.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        pie.setAttribute("vector-effect", "non-scaling-stroke")
-        pie.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(pie)
-      break
-    case "chord":
-      const chord = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算弦形的参数
-      const chordRadiusX = element.width * 0.4
-      const chordRadiusY = element.height * 0.4
-      // 绘制弦形 - 使用更大的圆弧和不同的起始/结束点
-      chord.setAttribute(
-        "d",
-        `M${element.width * 0.4},${element.height * 0.9} ` +
-          `A ${chordRadiusX} ${chordRadiusY} 0 1 1 ${element.width * 0.8},${
-            element.height * 0.5
-          } ` +
-          `Z`
-      )
-
-      // 设置填充色
-      setBackground(element, chord)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        chord.setAttribute("stroke", element.borderColor || "#000")
-        chord.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            chord.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            chord.setAttribute("stroke-dasharray", "2, 2")
-            chord.setAttribute("stroke-linecap", "round")
-          } else if (element.borderType === "dashed") {
-            chord.setAttribute("stroke-dasharray", "6, 3")
-          }
-        }
-
-        chord.setAttribute("vector-effect", "non-scaling-stroke")
-        chord.setAttribute("shape-rendering", "geometricPrecision")
-      }
-
-      svg.appendChild(chord)
-      break
-    case "heptagon":
-      const heptagon = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-
-      // 计算七边形的顶点
-      let heptagonPoints = ""
-      for (let i = 0; i < 7; i++) {
-        const angle = (i * 2 * Math.PI) / 7 - Math.PI / 2 // 从顶部开始
-        const x = element.width / 2 + (element.width / 2) * Math.cos(angle)
-        const y = element.height / 2 + (element.height / 2) * Math.sin(angle)
-        heptagonPoints += `${x},${y} `
-      }
-      heptagon.setAttribute("points", heptagonPoints.trim())
-
-      // 设置填充色
-      setBackground(element, heptagon)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        heptagon.setAttribute("stroke", element.borderColor || "#000")
-        heptagon.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            heptagon.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            heptagon.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            heptagon.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(heptagon)
-      break
-    case "hexagon":
-      const hexagon = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      hexagon.setAttribute(
-        "points",
-        `${element.width * 0.25},0 ${element.width * 0.75},0 ${element.width},${
-          element.height * 0.5
-        } ` +
-          `${element.width * 0.75},${element.height} ${element.width * 0.25},${
-            element.height
-          } 0,${element.height * 0.5}`
-      )
-
-      // 设置填充色
-      setBackground(element, hexagon)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        hexagon.setAttribute("stroke", element.borderColor || "#000")
-        hexagon.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            hexagon.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            hexagon.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            hexagon.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(hexagon)
-      break
-
-    case "octagon":
-      const octagon = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      octagon.setAttribute(
-        "points",
-        `${element.width * 0.3},0 ${element.width * 0.7},0 ${element.width},${
-          element.height * 0.3
-        } ` +
-          `${element.width},${element.height * 0.7} ${element.width * 0.7},${
-            element.height
-          } ` +
-          `${element.width * 0.3},${element.height} 0,${
-            element.height * 0.7
-          } 0,${element.height * 0.3}`
-      )
-
-      // 设置填充色
-      setBackground(element, octagon)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        octagon.setAttribute("stroke", element.borderColor || "#000")
-        octagon.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            octagon.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            octagon.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            octagon.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(octagon)
-      break
-
-    case "trapezoid":
-      const trapezoid = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      trapezoid.setAttribute(
-        "points",
-        `${element.width * 0.2},0 ${element.width * 0.8},0 ${element.width},${
-          element.height
-        } 0,${element.height}`
-      )
-
-      // 设置填充色
-      setBackground(element, trapezoid)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        trapezoid.setAttribute("stroke", element.borderColor || "#000")
-        trapezoid.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            trapezoid.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            trapezoid.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            trapezoid.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(trapezoid)
-      break
-
-    case "diamond":
-      const diamond = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      diamond.setAttribute(
-        "points",
-        `${element.width / 2},0 ${element.width},${element.height / 2} ${
-          element.width / 2
-        },${element.height} 0,${element.height / 2}`
-      )
-
-      // 设置填充色
-      setBackground(element, diamond)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        diamond.setAttribute("stroke", element.borderColor || "#000")
-        diamond.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            diamond.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            diamond.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            diamond.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(diamond)
-      break
-    case "dodecagon":
-      const dodecagon = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-
-      // 计算十二边形的顶点
-      let dodecagonPoints = ""
-      for (let i = 0; i < 12; i++) {
-        const angle = (i * 2 * Math.PI) / 12 - Math.PI / 2 // 从顶部开始
-        const x = element.width / 2 + (element.width / 2) * Math.cos(angle)
-        const y = element.height / 2 + (element.height / 2) * Math.sin(angle)
-        dodecagonPoints += `${x},${y} `
-      }
-      dodecagon.setAttribute("points", dodecagonPoints.trim())
-
-      // 设置填充色
-      setBackground(element, dodecagon)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        dodecagon.setAttribute("stroke", element.borderColor || "#000")
-        dodecagon.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            dodecagon.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            dodecagon.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            dodecagon.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(dodecagon)
-      break
-    case "halfFrame":
-      // 创建外框和内框
-      const outerRect2 = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      const innerRect2 = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      const halfFrameFmlaTop = element.formulas
-        ? element?.formulas[0].split(" ")[1]
-        : 20000
-      const halfFrameFmlaLeft = element.formulas
-        ? element?.formulas[1].split(" ")[1]
-        : 20000
-      const frameWidthTop = element.height * (halfFrameFmlaTop / 100000)
-      const frameWidthLeft = element.width * (halfFrameFmlaLeft / 100000)
-      // 绘制外框的左边和上边
-      outerRect2.setAttribute(
-        "d",
-        `M0,${element.height} L0,0 L${element.width},0`
-      )
-
-      // 绘制内框的左边和上边,注意起点位置调整
-      innerRect2.setAttribute(
-        "d",
-        `M${frameWidthLeft},${element.height - frameWidthLeft} ` +
-          `L${frameWidthLeft},${frameWidthTop} ` +
-          `L${element.width - frameWidthTop},${frameWidthTop}`
-      )
-
-      // 设置填充色
-      if (element.fill && element.fill.type === "color") {
-        // 创建一个填充用的路径
-        const fillPath = document.createElementNS(
-          "http://www.w3.org/2000/svg",
-          "path"
-        )
-        fillPath.setAttribute(
-          "d",
-          `M${frameWidthLeft},${frameWidthTop} ` +
-            `L${element.width - frameWidthTop},${frameWidthTop} ` +
-            `L${element.width},0 ` +
-            `L0,0 ` +
-            `L0,${element.height} ` +
-            `L${frameWidthLeft},${element.height - frameWidthLeft} Z`
-        )
-        fillPath.setAttribute("fill", element.fill.value || "transparent")
-        svg.appendChild(fillPath)
-
-        outerRect2.setAttribute("fill", "none")
-        innerRect2.setAttribute("fill", "none")
-      } else {
-        outerRect2.setAttribute("fill", "none")
-        innerRect2.setAttribute("fill", "none")
-      }
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        const borderColor = element.borderColor || "#000"
-        const borderWidth = element.borderWidth || 1
-
-        outerRect2.setAttribute("stroke", borderColor)
-        outerRect2.setAttribute("stroke-width", borderWidth)
-        innerRect2.setAttribute("stroke", borderColor)
-        innerRect2.setAttribute("stroke-width", borderWidth)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            const dashArray = element.borderStrokeDasharray
-            outerRect2.setAttribute("stroke-dasharray", dashArray)
-            innerRect2.setAttribute("stroke-dasharray", dashArray)
-          } else if (element.borderType === "dotted") {
-            outerRect2.setAttribute("stroke-dasharray", "1, 3")
-            innerRect2.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            outerRect2.setAttribute("stroke-dasharray", "5, 5")
-            innerRect2.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(outerRect2)
-      svg.appendChild(innerRect2)
-      break
-    case "corner":
-      const corner = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      corner.setAttribute(
-        "d",
-        `M0,0 ` +
-          `L0,${element.height} ` +
-          `L${element.width},${element.height} ` +
-          `L${element.width},${element.height * 0.6} ` +
-          `L${element.width * 0.4},${element.height * 0.6} ` +
-          `L${element.width * 0.4},0 Z`
-      )
-
-      // 设置填充色
-      setBackground(element, corner)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        corner.setAttribute("stroke", element.borderColor || "#000")
-        corner.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            corner.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            corner.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            corner.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(corner)
-      break
-    case "diagStripe":
-      const diagStripe = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 绘制斜纹路径
-      diagStripe.setAttribute(
-        "d",
-        `M${element.width * 0.4},0 ` +
-          `L${element.width},0 ` +
-          `L0,${element.height} ` +
-          `L0,${element.height * 0.4} Z`
-      )
-
-      // 设置填充色
-      setBackground(element, diagStripe)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        diagStripe.setAttribute("stroke", element.borderColor || "#000")
-        diagStripe.setAttribute("stroke-width", element.borderWidth || 1)
-        diagStripe.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            diagStripe.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            diagStripe.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            diagStripe.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(diagStripe)
-      break
-    case "plus":
-      const plus = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      plus.setAttribute(
-        "points",
-        `${element.width * 0.4},0 ` +
-          `${element.width * 0.6},0 ` +
-          `${element.width * 0.6},${element.height * 0.4} ` +
-          `${element.width},${element.height * 0.4} ` +
-          `${element.width},${element.height * 0.6} ` +
-          `${element.width * 0.6},${element.height * 0.6} ` +
-          `${element.width * 0.6},${element.height} ` +
-          `${element.width * 0.4},${element.height} ` +
-          `${element.width * 0.4},${element.height * 0.6} ` +
-          `0,${element.height * 0.6} ` +
-          `0,${element.height * 0.4} ` +
-          `${element.width * 0.4},${element.height * 0.4}`
-      )
-
-      // 设置填充色
-      setBackground(element, plus)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        plus.setAttribute("stroke", element.borderColor || "#000")
-        plus.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            plus.setAttribute("stroke-dasharray", element.borderStrokeDasharray)
-          } else if (element.borderType === "dotted") {
-            plus.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            plus.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(plus)
-      break
-    case "can":
-      const can = document.createElementNS("http://www.w3.org/2000/svg", "g")
-
-      // 创建圆柱体的主体部分
-      const cylinderBody = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      cylinderBody.setAttribute(
-        "d",
-        `M0,${element.height * 0.15} ` +
-          `A${element.width / 2},${element.height * 0.15} 0 0 1 ${
-            element.width
-          },${element.height * 0.15} ` +
-          `V${element.height * 0.85} ` +
-          `A${element.width / 2},${element.height * 0.15} 0 0 1 0,${
-            element.height * 0.85
-          } Z`
-      )
-
-      // 创建顶部椭圆
-      const topEllipse = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "ellipse"
-      )
-      topEllipse.setAttribute("cx", element.width / 2)
-      topEllipse.setAttribute("cy", element.height * 0.15)
-      topEllipse.setAttribute("rx", element.width / 2)
-      topEllipse.setAttribute("ry", element.height * 0.15)
-
-      // 设置填充色
-      setBackground(element, cylinderBody)
-      setBackground(element, topEllipse)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        const borderColor = element.borderColor || "#000"
-        const borderWidth = element.borderWidth || 1
-
-        cylinderBody.setAttribute("stroke", borderColor)
-        cylinderBody.setAttribute("stroke-width", borderWidth)
-        topEllipse.setAttribute("stroke", borderColor)
-        topEllipse.setAttribute("stroke-width", borderWidth)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            const dashArray = element.borderStrokeDasharray
-            cylinderBody.setAttribute("stroke-dasharray", dashArray)
-            topEllipse.setAttribute("stroke-dasharray", dashArray)
-          } else if (element.borderType === "dotted") {
-            cylinderBody.setAttribute("stroke-dasharray", "1, 3")
-            topEllipse.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            cylinderBody.setAttribute("stroke-dasharray", "5, 5")
-            topEllipse.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      can.appendChild(cylinderBody)
-      can.appendChild(topEllipse)
-      svg.appendChild(can)
-      break
-    case "cube":
-      const cube = document.createElementNS("http://www.w3.org/2000/svg", "g")
-
-      // 计算关键点坐标
-      const offset = element.width * 0.2
-      const frontX = offset
-      const frontY = offset
-      const frontW = element.width - offset
-      const frontH = element.height
-
-      // 设置立方体的三个面的路径
-      const frontFace = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      frontFace.setAttribute(
-        "d",
-        `M${frontX},${frontY} ` +
-          `L${frontW},${frontY} ` +
-          `L${frontW},${frontH} ` +
-          `L${frontX},${frontH} Z`
-      )
-
-      const rightFace = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      rightFace.setAttribute(
-        "d",
-        `M${frontW},${frontY} ` +
-          `L${element.width},0 ` +
-          `L${element.width},${element.height - offset} ` +
-          `L${frontW},${frontH} Z`
-      )
-
-      const topFace = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      topFace.setAttribute(
-        "d",
-        `M${frontX},${frontY} ` +
-          `L${frontW - offset - frontX},0 ` + // 修改这里:改为从(0,0)开始
-          `L${element.width - offset},0 ` + // 修改这里:使用 offset 来计算右上角的位置
-          `L${element.width},0 ` +
-          `L${frontW},${frontY} Z`
-      )
-
-      // 设置填充色
-      if (element.fill && element.fill.type === "color") {
-        const fillColor = element.fill.value || "transparent"
-        frontFace.setAttribute("fill", fillColor)
-        rightFace.setAttribute("fill", adjustBrightness(fillColor, 0.8))
-        topFace.setAttribute("fill", adjustBrightness(fillColor, 1.2))
-      } else {
-        frontFace.setAttribute("fill", "transparent")
-        rightFace.setAttribute("fill", "transparent")
-        topFace.setAttribute("fill", "transparent")
-      }
-      // 设置边框
-      if (element.borderWidth > 0) {
-        const borderColor = element.borderColor || "#000"
-        const borderWidth = element.borderWidth || 1
-
-        frontFace.setAttribute("stroke", borderColor)
-        frontFace.setAttribute("stroke-width", borderWidth)
-        rightFace.setAttribute("stroke", borderColor)
-        rightFace.setAttribute("stroke-width", borderWidth)
-        topFace.setAttribute("stroke", borderColor)
-        topFace.setAttribute("stroke-width", borderWidth)
-
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          const dashArray =
-            element.borderStrokeDasharray ||
-            (element.borderType === "dotted" ? "1, 3" : "5, 5")
-          frontFace.setAttribute("stroke-dasharray", dashArray)
-          rightFace.setAttribute("stroke-dasharray", dashArray)
-          topFace.setAttribute("stroke-dasharray", dashArray)
-        }
-      }
-
-      // 按正确的顺序添加面(从后到前)
-      cube.appendChild(rightFace)
-      cube.appendChild(topFace)
-      cube.appendChild(frontFace)
-      svg.appendChild(cube)
-      break
-    case "bevel":
-      const bevel = document.createElementNS("http://www.w3.org/2000/svg", "g")
-
-      // 计算关键点坐标
-      const bevelOffset = element.width * 0.2
-      const smallRectX = bevelOffset
-      const smallRectY = bevelOffset
-      const smallRectW = element.width - 2 * bevelOffset
-      const smallRectH = element.height - 2 * bevelOffset
-
-      // 绘制顶部小矩形
-      const topRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "rect"
-      )
-      topRect.setAttribute("x", smallRectX)
-      topRect.setAttribute("y", smallRectY)
-      topRect.setAttribute("width", smallRectW)
-      topRect.setAttribute("height", smallRectH)
-
-      // 绘制四个梯形
-      const topTrapezoid = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      topTrapezoid.setAttribute(
-        "d",
-        `M0,0 L${element.width},0 L${
-          element.width - bevelOffset
-        },${bevelOffset} L${bevelOffset},${bevelOffset} Z`
-      )
-
-      const bottomTrapezoid = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      bottomTrapezoid.setAttribute(
-        "d",
-        `M${bevelOffset},${element.height - bevelOffset} L${
-          element.width - bevelOffset
-        },${element.height - bevelOffset} L${element.width},${
-          element.height
-        } L0,${element.height} Z`
-      )
-
-      const leftTrapezoid = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      leftTrapezoid.setAttribute(
-        "d",
-        `M0,0 L${bevelOffset},${bevelOffset} L${bevelOffset},${
-          element.height - bevelOffset
-        } L0,${element.height} Z`
-      )
-
-      const rightTrapezoid = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      rightTrapezoid.setAttribute(
-        "d",
-        `M${element.width},0 L${element.width},${element.height} L${
-          element.width - bevelOffset
-        },${element.height - bevelOffset} L${
-          element.width - bevelOffset
-        },${bevelOffset} Z`
-      )
-
-      // 设置填充色
-      if (element.fill && element.fill.type === "color") {
-        const fillColor = element.fill.value || "transparent"
-        topRect.setAttribute("fill", fillColor)
-        topTrapezoid.setAttribute("fill", adjustBrightness(fillColor, 1.2))
-        bottomTrapezoid.setAttribute("fill", adjustBrightness(fillColor, 0.8))
-        leftTrapezoid.setAttribute("fill", adjustBrightness(fillColor, 0.9))
-        rightTrapezoid.setAttribute("fill", adjustBrightness(fillColor, 0.7))
-      } else {
-        topRect.setAttribute("fill", "transparent")
-        topTrapezoid.setAttribute("fill", "transparent")
-        bottomTrapezoid.setAttribute("fill", "transparent")
-        leftTrapezoid.setAttribute("fill", "transparent")
-        rightTrapezoid.setAttribute("fill", "transparent")
-      }
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        const borderColor = element.borderColor || "#000"
-        const borderWidth = element.borderWidth || 1
-        const parts = [
-          topRect,
-          topTrapezoid,
-          bottomTrapezoid,
-          leftTrapezoid,
-          rightTrapezoid,
-        ]
-
-        parts.forEach((part) => {
-          part.setAttribute("stroke", borderColor)
-          part.setAttribute("stroke-width", borderWidth)
-
-          if (
-            element.borderType === "dotted" ||
-            element.borderType === "dashed"
-          ) {
-            const dashArray =
-              element.borderStrokeDasharray ||
-              (element.borderType === "dotted" ? "1, 3" : "5, 5")
-            part.setAttribute("stroke-dasharray", dashArray)
-          }
-        })
-      }
-
-      // 按正确的顺序添加面(从后到前)
-      bevel.appendChild(bottomTrapezoid)
-      bevel.appendChild(leftTrapezoid)
-      bevel.appendChild(rightTrapezoid)
-      bevel.appendChild(topTrapezoid)
-      bevel.appendChild(topRect)
-      svg.appendChild(bevel)
-      break
-    case "donut":
-    case "donut":
-      const donut = document.createElementNS("http://www.w3.org/2000/svg", "g")
-
-      // 外圆
-      const outerCircle = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "circle"
-      )
-      outerCircle.setAttribute("cx", element.width / 2)
-      outerCircle.setAttribute("cy", element.height / 2)
-      outerCircle.setAttribute("r", Math.min(element.width, element.height) / 2)
-
-      // 内圆
-      const innerCircle = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "circle"
-      )
-      const fmla = element?.formulas[0].split(" ")[1]
-      innerCircle.setAttribute("cx", element.width / 2)
-      innerCircle.setAttribute("cy", element.height / 2)
-      innerCircle.setAttribute(
-        "r",
-        (Math.min(element.width, element.height) / 2) *
-          (1 - Math.sqrt(fmla / 100000) / 2)
-      )
-
-      // 设置填充色
-      setBackground(element, outerCircle)
-      innerCircle.setAttribute("fill", "white")
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        const borderColor = element.borderColor || "#000"
-        const borderWidth = element.borderWidth || 1
-
-        outerCircle.setAttribute("stroke", borderColor)
-        outerCircle.setAttribute("stroke-width", borderWidth)
-        innerCircle.setAttribute("stroke", borderColor)
-        innerCircle.setAttribute("stroke-width", borderWidth)
-
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          const dashArray =
-            element.borderStrokeDasharray ||
-            (element.borderType === "dotted" ? "1, 3" : "5, 5")
-          outerCircle.setAttribute("stroke-dasharray", dashArray)
-          innerCircle.setAttribute("stroke-dasharray", dashArray)
-        }
-      }
-
-      donut.appendChild(outerCircle)
-      donut.appendChild(innerCircle)
-      svg.appendChild(donut)
-      break
-    case "noSmoking":
-      const noSmoking = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "g"
-      )
-
-      // 创建路径
-      const path = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      path.setAttribute(
-        "d",
-        "M0,70 A77,70 0 1,1 0,71 Z M123.80284467265982,99.39738105155146 A57.5386,50.5386 0 0 0 45.160427644134444,27.90427466198293 Z M30.197155327340184,40.602618948448544 A57.5386,50.5386 0 0 0 108.83957235586556,112.09572533801708 Z"
-      )
-      path.setAttribute("fill", "rgba(255,217,102,1)")
-      path.setAttribute("stroke", "rgba(23,44,81,1)")
-      path.setAttribute("stroke-width", "1px")
-      path.setAttribute("stroke-dasharray", "")
-      path.setAttribute("stroke-linecap", "butt")
-      path.setAttribute("stroke-linejoin", "round")
-
-      noSmoking.appendChild(path)
-      svg.appendChild(noSmoking)
-      break
-    case "rightArrow":
-      const rightArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      rightArrow.setAttribute(
-        "points",
-        `0,${element.height * 0.3} ${element.width * 0.7},${
-          element.height * 0.3
-        } ` +
-          `${element.width * 0.7},0 ${element.width},${element.height * 0.5} ` +
-          `${element.width * 0.7},${element.height} ${element.width * 0.7},${
-            element.height * 0.7
-          } ` +
-          `0,${element.height * 0.7}`
-      )
-
-      // 设置填充色
-      setBackground(element, rightArrow)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        rightArrow.setAttribute("stroke", element.borderColor || "#000")
-        rightArrow.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            rightArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            rightArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            rightArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(rightArrow)
-      break
-    case "leftArrow":
-      const leftArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      leftArrow.setAttribute(
-        "points",
-        `${element.width},${element.height * 0.3} ${element.width * 0.3},${
-          element.height * 0.3
-        } ` +
-          `${element.width * 0.3},0 0,${element.height * 0.5} ` +
-          `${element.width * 0.3},${element.height} ${element.width * 0.3},${
-            element.height * 0.7
-          } ` +
-          `${element.width},${element.height * 0.7}`
-      )
-
-      // 设置填充色
-      setBackground(element, leftArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        leftArrow.setAttribute("stroke", element.borderColor || "#000")
-        leftArrow.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            leftArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            leftArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            leftArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(leftArrow)
-      break
-    case "upArrow":
-      const upArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      upArrow.setAttribute(
-        "points",
-        `${element.width * 0.3},${element.height} ${element.width * 0.3},${
-          element.height * 0.3
-        } ` +
-          `0,${element.height * 0.3} ${element.width * 0.5},0 ` +
-          `${element.width},${element.height * 0.3} ${element.width * 0.7},${
-            element.height * 0.3
-          } ` +
-          `${element.width * 0.7},${element.height}`
-      )
-
-      // 设置填充色
-      setBackground(element, upArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        upArrow.setAttribute("stroke", element.borderColor || "#000")
-        upArrow.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            upArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            upArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            upArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(upArrow)
-      break
-    case "downArrow":
-      const downArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      downArrow.setAttribute(
-        "points",
-        `${element.width * 0.3},0 ${element.width * 0.3},${
-          element.height * 0.7
-        } ` +
-          `0,${element.height * 0.7} ${element.width * 0.5},${
-            element.height
-          } ` +
-          `${element.width},${element.height * 0.7} ${element.width * 0.7},${
-            element.height * 0.7
-          } ` +
-          `${element.width * 0.7},0`
-      )
-
-      // 设置填充色
-      setBackground(element, downArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        downArrow.setAttribute("stroke", element.borderColor || "#000")
-        downArrow.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            downArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            downArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            downArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(downArrow)
-      break
-    case "leftRightArrow":
-      const leftRightArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      leftRightArrow.setAttribute(
-        "points",
-        `0,${element.height * 0.5} ${element.width * 0.2},${
-          element.height * 0.2
-        } ` +
-          `${element.width * 0.2},${element.height * 0.4} ${
-            element.width * 0.8
-          },${element.height * 0.4} ` +
-          `${element.width * 0.8},${element.height * 0.2} ${element.width},${
-            element.height * 0.5
-          } ` +
-          `${element.width * 0.8},${element.height * 0.8} ${
-            element.width * 0.8
-          },${element.height * 0.6} ` +
-          `${element.width * 0.2},${element.height * 0.6} ${
-            element.width * 0.2
-          },${element.height * 0.8}`
-      )
-
-      // 设置填充色
-      setBackground(element, leftRightArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        leftRightArrow.setAttribute("stroke", element.borderColor || "#000")
-        leftRightArrow.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            leftRightArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            leftRightArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            leftRightArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(leftRightArrow)
-      break
-    case "upDownArrow":
-      const upDownArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      upDownArrow.setAttribute(
-        "points",
-        `${element.width * 0.5},0 ${element.width * 0.3},${
-          element.height * 0.2
-        } ` +
-          `${element.width * 0.4},${element.height * 0.2} ${
-            element.width * 0.4
-          },${element.height * 0.8} ` +
-          `${element.width * 0.3},${element.height * 0.8} ${
-            element.width * 0.5
-          },${element.height} ` +
-          `${element.width * 0.7},${element.height * 0.8} ${
-            element.width * 0.6
-          },${element.height * 0.8} ` +
-          `${element.width * 0.6},${element.height * 0.2} ${
-            element.width * 0.7
-          },${element.height * 0.2}`
-      )
-
-      // 设置填充色
-      setBackground(element, upDownArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        upDownArrow.setAttribute("stroke", element.borderColor || "#000")
-        upDownArrow.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            upDownArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            upDownArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            upDownArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(upDownArrow)
-      break
-    case "quadArrow":
-      const quadArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算缩放比例
-      const scale = Math.min(element.width / 167, element.height / 121)
-      const offsetX = (element.width - 167 * scale) / 2
-      const offsetY = (element.height - 121 * scale) / 2
-
-      // 构建路径数据
-      const pathData = `
-          M${offsetX},${60.5 * scale + offsetY}
-          L${27.225 * scale + offsetX},${33.275 * scale + offsetY}
-          L${27.225 * scale + offsetX},${46.8875 * scale + offsetY}
-          L${69.8875 * scale + offsetX},${46.8875 * scale + offsetY}
-          L${69.8875 * scale + offsetX},${27.225 * scale + offsetY}
-          L${56.275 * scale + offsetX},${27.225 * scale + offsetY}
-          L${83.5 * scale + offsetX},${offsetY}
-          L${110.725 * scale + offsetX},${27.225 * scale + offsetY}
-          L${97.1125 * scale + offsetX},${27.225 * scale + offsetY}
-          L${97.1125 * scale + offsetX},${46.8875 * scale + offsetY}
-          L${139.775 * scale + offsetX},${46.8875 * scale + offsetY}
-          L${139.775 * scale + offsetX},${33.275 * scale + offsetY}
-          L${167 * scale + offsetX},${60.5 * scale + offsetY}
-          L${139.775 * scale + offsetX},${87.725 * scale + offsetY}
-          L${139.775 * scale + offsetX},${74.1125 * scale + offsetY}
-          L${97.1125 * scale + offsetX},${74.1125 * scale + offsetY}
-          L${97.1125 * scale + offsetX},${93.775 * scale + offsetY}
-          L${110.725 * scale + offsetX},${93.775 * scale + offsetY}
-          L${83.5 * scale + offsetX},${121 * scale + offsetY}
-          L${56.275 * scale + offsetX},${93.775 * scale + offsetY}
-          L${69.8875 * scale + offsetX},${93.775 * scale + offsetY}
-          L${69.8875 * scale + offsetX},${74.1125 * scale + offsetY}
-          L${27.225 * scale + offsetX},${74.1125 * scale + offsetY}
-          L${27.225 * scale + offsetX},${87.725 * scale + offsetY}
-          Z`
-
-      quadArrow.setAttribute("d", pathData)
-
-      // 设置填充色
-      setBackground(element, quadArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        quadArrow.setAttribute("stroke", element.borderColor || "#000")
-        quadArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        quadArrow.setAttribute("stroke-linecap", "butt")
-        quadArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            quadArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            quadArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            quadArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(quadArrow)
-      break
-    case "leftRightUpArrow":
-      const leftRightUpArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算缩放比例
-      const scale2 = Math.min(element.width / 167, element.height / 121)
-      const offsetX2 = (element.width - 167 * scale2) / 2
-      const offsetY2 = (element.height - 121 * scale2) / 2
-
-      // 构建路径数据
-      const pathData2 = `
-          M${offsetX2},${60.5 * scale2 + offsetY2}
-          L${27.225 * scale2 + offsetX2},${33.275 * scale2 + offsetY2}
-          L${27.225 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
-          L${69.8875 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
-          L${69.8875 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
-          L${56.275 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
-          L${83.5 * scale2 + offsetX2},${offsetY2}
-          L${110.725 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
-          L${97.1125 * scale2 + offsetX2},${27.225 * scale2 + offsetY2}
-          L${97.1125 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
-          L${139.775 * scale2 + offsetX2},${46.8875 * scale2 + offsetY2}
-          L${139.775 * scale2 + offsetX2},${33.275 * scale2 + offsetY2}
-          L${167 * scale2 + offsetX2},${60.5 * scale2 + offsetY2}
-          L${139.775 * scale2 + offsetX2},${87.725 * scale2 + offsetY2}
-          L${139.775 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
-          L${97.1125 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
-          L${69.8875 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
-          L${27.225 * scale2 + offsetX2},${74.1125 * scale2 + offsetY2}
-          L${27.225 * scale2 + offsetX2},${87.725 * scale2 + offsetY2}
-          Z`
-
-      leftRightUpArrow.setAttribute("d", pathData2)
-
-      // 设置填充色
-      setBackground(element, leftRightUpArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        leftRightUpArrow.setAttribute("stroke", element.borderColor || "#000")
-        leftRightUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        leftRightUpArrow.setAttribute("stroke-linecap", "butt")
-        leftRightUpArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            leftRightUpArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            leftRightUpArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            leftRightUpArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(leftRightUpArrow)
-      break
-    case "bentArrow":
-      const bentArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 构建路径数据
-      const pathData3 = `
-          M0,${element.height * 0.88}
-          L0,${element.height * 0.495}
-          A${element.width * 0.385} ${element.height * 0.385} 0 0 1 ${
-        element.width * 0.385
-      } ${element.height * 0.11}
-          L${element.width * 0.67},${element.height * 0.11}
-          L${element.width * 0.67},0
-          L${element.width * 0.89},${element.height * 0.22}
-          L${element.width * 0.67},${element.height * 0.44}
-          L${element.width * 0.67},${element.height * 0.33}
-          L${element.width * 0.385},${element.height * 0.33}
-          A${element.width * 0.165} ${element.height * 0.165} 0 0 0 ${
-        element.width * 0.22
-      } ${element.height * 0.495}
-          L${element.width * 0.22},${element.height * 0.88}
-          Z`
-
-      bentArrow.setAttribute("d", pathData3)
-
-      // 设置填充色
-      setBackground(element, bentArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        bentArrow.setAttribute("stroke", element.borderColor || "#000")
-        bentArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        bentArrow.setAttribute("stroke-linecap", "butt")
-        bentArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            bentArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            bentArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            bentArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(bentArrow)
-      break
-    case "parallelogram":
-      const parallelogram = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      parallelogram.setAttribute(
-        "points",
-        `${element.width * 0.25},0 ${element.width},0 ${element.width * 0.75},${
-          element.height
-        } 0,${element.height}`
-      )
-
-      // 设置填充色
-      setBackground(element, parallelogram)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        parallelogram.setAttribute("stroke", element.borderColor || "#000")
-        parallelogram.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            parallelogram.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            parallelogram.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            parallelogram.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(parallelogram)
-      break
-    case "uturnArrow":
-      const uturnArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 构建路径数据
-      const pathDataUturn = `
-          M0,${element.height * 0.745}
-          L0,${element.height * 0.179375}
-          A${element.width * 0.179375} ${element.height * 0.179375} 0 0 1 ${
-        element.width * 0.179375
-      },0
-          L${element.width * 0.179375},0
-          A${element.width * 0.179375} ${element.height * 0.179375} 0 0 1 ${
-        element.width * 0.359375
-      },${element.height * 0.179375}
-          L${element.width * 0.359375},${element.height * 0.205}
-          L${element.width * 0.41},${element.height * 0.205}
-          L${element.width * 0.3075},${element.height * 0.3075}
-          L${element.width * 0.205},${element.height * 0.205}
-          L${element.width * 0.25625},${element.height * 0.205}
-          L${element.width * 0.25625},${element.height * 0.179375}
-          A${element.width * 0.076875} ${element.height * 0.076875} 0 0 0 ${
-        element.width * 0.179375
-      },${element.height * 0.1025}
-          L${element.width * 0.179375},${element.height * 0.1025}
-          A${element.width * 0.076875} ${element.height * 0.076875} 0 0 0 ${
-        element.width * 0.1025
-      },${element.height * 0.179375}
-          L${element.width * 0.1025},${element.height * 0.745}
-          Z`
-
-      uturnArrow.setAttribute("d", pathDataUturn)
-
-      // 设置填充色
-      setBackground(element, uturnArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        uturnArrow.setAttribute("stroke", element.borderColor || "#000")
-        uturnArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        uturnArrow.setAttribute("stroke-linecap", "butt")
-        uturnArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            uturnArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            uturnArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            uturnArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(uturnArrow)
-      break
-    case "leftUpArrow":
-      const leftUpArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 使用提供的路径数据
-      const pathDataLeftUp = `
-          M0,${element.height * 0.65}
-          L${element.width * 0.15},${element.height * 0.4}
-          L${element.width * 0.15},${element.height * 0.55}
-          L${element.width * 0.5},${element.height * 0.55}
-          L${element.width * 0.5},${element.height * 0.1}
-          L${element.width * 0.35},${element.height * 0.1}
-          L${element.width * 0.65},0
-          L${element.width * 0.85},${element.height * 0.1}
-          L${element.width * 0.75},${element.height * 0.1}
-          L${element.width * 0.75},${element.height * 0.85}
-          L${element.width * 0.15},${element.height * 0.85}
-          L${element.width * 0.15},${element.height * 1}
-          Z`
-
-      leftUpArrow.setAttribute("d", pathDataLeftUp)
-
-      // 设置填充色
-      setBackground(element, leftUpArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        leftUpArrow.setAttribute("stroke", element.borderColor || "#000")
-        leftUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        leftUpArrow.setAttribute("stroke-linecap", "butt")
-        leftUpArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            leftUpArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            leftUpArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            leftUpArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(leftUpArrow)
-      break
-    case "bentUpArrow":
-      const bentUpArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 构建路径数据,去掉左侧箭头
-      // 使用提供的路径数据
-      const pathDataBentUp = `
-          M0,${element.height * 0.89}
-          L0,${element.height * 0.7}
-          L${element.width * 0.575},${element.height * 0.7}
-          L${element.width * 0.575},${element.height * 0.2}
-          L${element.width * 0.46},${element.height * 0.2}
-          L${element.width * 0.69},0
-          L${element.width * 0.92},${element.height * 0.2}
-          L${element.width * 0.805},${element.height * 0.2}
-          L${element.width * 0.805},${element.height * 0.89}
-          Z`
-
-      bentUpArrow.setAttribute("d", pathDataBentUp)
-
-      // 设置填充色
-      setBackground(element, bentUpArrow)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        bentUpArrow.setAttribute("stroke", element.borderColor || "#000")
-        bentUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        bentUpArrow.setAttribute("stroke-linecap", "butt")
-        bentUpArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            bentUpArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            bentUpArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            bentUpArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(bentUpArrow)
-      break
-    case "curvedRightArrow":
-      const curvedRightArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 使用提供的路径数据
-      const pathDataCurvedRight = `
-          M${element.width},0
-          A${element.width} ${element.height * 0.4} 0 0 0 0 ${
-        element.height * 0.4
-      }
-          L0,${element.height * 0.5}
-          A${element.width} ${element.height * 0.4} 0 0 1 ${element.width} ${
-        element.height * 0.15
-      }
-          Z
-          M0,${element.height * 0.4}
-          A${element.width} ${element.height * 0.4} 0 0 0 ${
-        element.width * 0.8
-      } ${element.height * 0.8}
-          L${element.width * 0.8},${element.height * 0.75}
-          L${element.width},${element.height * 0.875}
-          L${element.width * 0.8},${element.height * 1}
-          L${element.width * 0.8},${element.height * 0.95}
-          A${element.width} ${element.height * 0.4} 0 0 1 0 ${
-        element.height * 0.5
-      }
-          Z`
-
-      curvedRightArrow.setAttribute("d", pathDataCurvedRight)
-
-      // 设置填充色
-      setBackground(element, curvedRightArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        curvedRightArrow.setAttribute("stroke", element.borderColor || "#000")
-        curvedRightArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        curvedRightArrow.setAttribute("stroke-linecap", "butt")
-        curvedRightArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            curvedRightArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            curvedRightArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            curvedRightArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(curvedRightArrow)
-      break
-    case "curvedLeftArrow":
-      const curvedLeftArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 定义左弧形箭头的路径数据
-      const pathDataCurvedLeft = `
-          M0,0
-          A${element.width} ${element.height * 0.4} 0 0 1 ${element.width} ${
-        element.height * 0.4
-      }
-          L${element.width},${element.height * 0.55}
-          A${element.width} ${element.height * 0.4} 0 0 0 0 ${
-        element.height * 0.15
-      }
-          Z
-          M0,${element.height * 0.85}
-          L${element.width * 0.25},${element.height * 0.65}
-          L${element.width * 0.25},${element.height * 0.75}
-          A${element.width} ${element.height * 0.4} 0 0 0 ${element.width} ${
-        element.height * 0.4
-      }
-          L${element.width},${element.height * 0.5}
-          L${element.width},${element.height * 0.5}
-          A${element.width} ${element.height * 0.4} 0 0 1 ${
-        element.width * 0.25
-      } ${element.height * 0.9}
-          L${element.width * 0.25},${element.height}
-          Z`
-
-      curvedLeftArrow.setAttribute("d", pathDataCurvedLeft)
-
-      // 设置填充色
-      setBackground(element, curvedLeftArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        curvedLeftArrow.setAttribute("stroke", element.borderColor || "#000")
-        curvedLeftArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        curvedLeftArrow.setAttribute("stroke-linecap", "butt")
-        curvedLeftArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            curvedLeftArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            curvedLeftArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            curvedLeftArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(curvedLeftArrow)
-      break
-    case "curvedUpArrow":
-      const curvedUpArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 定义上弧形箭头的路径数据
-      const pathDataCurvedUp = `
-          M${element.width * 0.905},0
-          L${element.width * 0.81},${element.height * 0.25}
-          L${element.width * 0.857},${element.height * 0.25}
-          A${element.width * 0.428} ${element.height} 0 0 1 ${
-        element.width * 0.428
-      },${element.height}
-          L${element.width * 0.522},${element.height}
-          A${element.width * 0.428} ${element.height} 0 0 0 ${
-        element.width * 0.952
-      },${element.height * 0.25}
-          L${element.width},${element.height * 0.25}
-          Z
-          M${element.width * 0.094},0
-          L0,0
-          A${element.width * 0.428} ${element.height} 0 0 0 ${
-        element.width * 0.428
-      },${element.height}
-          L${element.width * 0.522},${element.height}
-          A${element.width * 0.428} ${element.height} 0 0 1 ${
-        element.width * 0.094
-      },0
-          Z`
-
-      curvedUpArrow.setAttribute("d", pathDataCurvedUp)
-
-      // 设置填充色
-      setBackground(element, curvedUpArrow)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        curvedUpArrow.setAttribute("stroke", element.borderColor || "#000")
-        curvedUpArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        curvedUpArrow.setAttribute("stroke-linecap", "butt")
-        curvedUpArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            curvedUpArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            curvedUpArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            curvedUpArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(curvedUpArrow)
-      break
-    case "curvedDownArrow":
-      const curvedDownArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 定义下弧形箭头的路径数据
-      const pathDataCurvedDown = `
-          M0,${element.height}
-          L${element.width * 0.16},${element.height}
-          A${element.width * 0.46} ${element.height} 0 0 1 ${
-        element.width * 0.62
-      },0
-          L${element.width * 0.46},0
-          A${element.width * 0.46} ${element.height} 0 0 0 0,${element.height}
-          Z
-          M${element.width},${element.height}
-          L${element.width * 0.84},${element.height * 0.75}
-          L${element.width * 0.92},${element.height * 0.75}
-          A${element.width * 0.46} ${element.height} 0 0 0 ${
-        element.width * 0.46
-      },0
-          L${element.width * 0.62},0
-          A${element.width * 0.46} ${element.height} 0 0 1 ${
-        element.width * 1.08
-      },${element.height * 0.75}
-          L${element.width * 1.16},${element.height * 0.75}
-          Z`
-
-      curvedDownArrow.setAttribute("d", pathDataCurvedDown)
-
-      // 设置填充色
-      setBackground(element, curvedDownArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        curvedDownArrow.setAttribute("stroke", element.borderColor || "#000")
-        curvedDownArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        curvedDownArrow.setAttribute("stroke-linecap", "butt")
-        curvedDownArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            curvedDownArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            curvedDownArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            curvedDownArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(curvedDownArrow)
-      break
-    case "stripedRightArrow":
-      const stripedRightArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "g"
-      )
-
-      // 主箭头部分
-      const mainArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      mainArrow.setAttribute(
-        "d",
-        `M${element.width * 0.062},${element.height * 0.25}
-          L${element.width * 0.8},${element.height * 0.25}
-          L${element.width * 0.8},0
-          L${element.width},${element.height * 0.5}
-          L${element.width * 0.8},${element.height}
-          L${element.width * 0.8},${element.height * 0.75}
-          L${element.width * 0.062},${element.height * 0.75}
-          Z`
-      )
-
-      // 第一条尾部条纹
-      const stripe1 = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      stripe1.setAttribute(
-        "d",
-        `M0,${element.height * 0.25}
-          L${element.width * 0.012},${element.height * 0.25}
-          L${element.width * 0.012},${element.height * 0.75}
-          L0,${element.height * 0.75}
-          Z`
-      )
-
-      // 第二条尾部条纹
-      const stripe2 = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      stripe2.setAttribute(
-        "d",
-        `M${element.width * 0.025},${element.height * 0.25}
-          L${element.width * 0.049},${element.height * 0.25}
-          L${element.width * 0.049},${element.height * 0.75}
-          L${element.width * 0.025},${element.height * 0.75}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, mainArrow)
-      setBackground(element, stripe1)
-      setBackground(element, stripe2)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        ;[mainArrow, stripe1, stripe2].forEach((path) => {
-          path.setAttribute("stroke", element.borderColor || "#000")
-          path.setAttribute("stroke-width", element.borderWidth || 1)
-          path.setAttribute("stroke-linecap", "butt")
-          path.setAttribute("stroke-linejoin", "round")
-
-          // 处理虚线边框
-          if (
-            element.borderType === "dotted" ||
-            element.borderType === "dashed"
-          ) {
-            if (element.borderStrokeDasharray) {
-              path.setAttribute(
-                "stroke-dasharray",
-                element.borderStrokeDasharray
-              )
-            } else if (element.borderType === "dotted") {
-              path.setAttribute("stroke-dasharray", "1, 3")
-            } else if (element.borderType === "dashed") {
-              path.setAttribute("stroke-dasharray", "5, 5")
-            }
-          }
-        })
-      }
-
-      stripedRightArrow.appendChild(mainArrow)
-      stripedRightArrow.appendChild(stripe1)
-      stripedRightArrow.appendChild(stripe2)
-      svg.appendChild(stripedRightArrow)
-      break
-    case "rightArrowCallout":
-      const rightArrowCallout = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      rightArrowCallout.setAttribute(
-        "d",
-        `M0,0
-          L${element.width * 0.44},0
-          L${element.width * 0.44},${element.height * 0.375}
-          L${element.width * 0.79},${element.height * 0.375}
-          L${element.width * 0.79},${element.height * 0.25}
-          L${element.width},${element.height * 0.5}
-          L${element.width * 0.79},${element.height * 0.75}
-          L${element.width * 0.79},${element.height * 0.625}
-          L${element.width * 0.44},${element.height * 0.625}
-          L${element.width * 0.44},${element.height}
-          L0,${element.height}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, rightArrowCallout)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        rightArrowCallout.setAttribute("stroke", element.borderColor || "#000")
-        rightArrowCallout.setAttribute("stroke-width", element.borderWidth || 1)
-        rightArrowCallout.setAttribute("stroke-linecap", "butt")
-        rightArrowCallout.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            rightArrowCallout.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            rightArrowCallout.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            rightArrowCallout.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(rightArrowCallout)
-      break
-    case "leftRightArrowCallout":
-      const leftRightArrowCallout = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      leftRightArrowCallout.setAttribute(
-        "d",
-        `M0,${element.height * 0.5}
-          L${element.width * 0.139},${element.height * 0.25}
-          L${element.width * 0.139},${element.height * 0.375}
-          L${element.width * 0.364},${element.height * 0.375}
-          L${element.width * 0.364},0
-          L${element.width * 0.636},0
-          L${element.width * 0.636},${element.height * 0.375}
-          L${element.width * 0.861},${element.height * 0.375}
-          L${element.width * 0.861},${element.height * 0.25}
-          L${element.width},${element.height * 0.5}
-          L${element.width * 0.861},${element.height * 0.75}
-          L${element.width * 0.861},${element.height * 0.625}
-          L${element.width * 0.636},${element.height * 0.625}
-          L${element.width * 0.636},${element.height}
-          L${element.width * 0.364},${element.height}
-          L${element.width * 0.364},${element.height * 0.625}
-          L${element.width * 0.139},${element.height * 0.625}
-          L${element.width * 0.139},${element.height * 0.75}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, leftRightArrowCallout)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        leftRightArrowCallout.setAttribute(
-          "stroke",
-          element.borderColor || "#000"
-        )
-        leftRightArrowCallout.setAttribute(
-          "stroke-width",
-          element.borderWidth || 1
-        )
-        leftRightArrowCallout.setAttribute("stroke-linecap", "butt")
-        leftRightArrowCallout.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            leftRightArrowCallout.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            leftRightArrowCallout.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            leftRightArrowCallout.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(leftRightArrowCallout)
-      break
-    case "quadArrowCallout":
-      const quadArrowCallout = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      quadArrowCallout.setAttribute(
-        "d",
-        `M0,${element.height * 0.5}
-          L${element.width * 0.096},${element.height * 0.315}
-          L${element.width * 0.096},${element.height * 0.407}
-          L${element.width * 0.26},${element.height * 0.407}
-          L${element.width * 0.26},${element.height * 0.259}
-          L${element.width * 0.453},${element.height * 0.259}
-          L${element.width * 0.453},${element.height * 0.185}
-          L${element.width * 0.405},${element.height * 0.185}
-          L${element.width * 0.5},0
-          L${element.width * 0.595},${element.height * 0.185}
-          L${element.width * 0.547},${element.height * 0.185}
-          L${element.width * 0.547},${element.height * 0.259}
-          L${element.width * 0.74},${element.height * 0.259}
-          L${element.width * 0.74},${element.height * 0.407}
-          L${element.width * 0.904},${element.height * 0.407}
-          L${element.width * 0.904},${element.height * 0.315}
-          L${element.width},${element.height * 0.5}
-          L${element.width * 0.904},${element.height * 0.685}
-          L${element.width * 0.904},${element.height * 0.593}
-          L${element.width * 0.74},${element.height * 0.593}
-          L${element.width * 0.74},${element.height * 0.741}
-          L${element.width * 0.547},${element.height * 0.741}
-          L${element.width * 0.547},${element.height * 0.815}
-          L${element.width * 0.595},${element.height * 0.815}
-          L${element.width * 0.5},${element.height}
-          L${element.width * 0.405},${element.height * 0.815}
-          L${element.width * 0.453},${element.height * 0.815}
-          L${element.width * 0.453},${element.height * 0.741}
-          L${element.width * 0.26},${element.height * 0.741}
-          L${element.width * 0.26},${element.height * 0.593}
-          L${element.width * 0.096},${element.height * 0.593}
-          L${element.width * 0.096},${element.height * 0.685}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, quadArrowCallout)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        quadArrowCallout.setAttribute("stroke", element.borderColor || "#000")
-        quadArrowCallout.setAttribute("stroke-width", element.borderWidth || 1)
-        quadArrowCallout.setAttribute("stroke-linecap", "butt")
-        quadArrowCallout.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            quadArrowCallout.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            quadArrowCallout.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            quadArrowCallout.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(quadArrowCallout)
-      break
-    case "leftArrowCallout":
-      const leftArrowCallout = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      leftArrowCallout.setAttribute(
-        "d",
-        `M0,${element.height * 0.5}
-          L${element.width * 0.183},${element.height * 0.25}
-          L${element.width * 0.183},${element.height * 0.375}
-          L${element.width * 0.35},${element.height * 0.375}
-          L${element.width * 0.35},0
-          L${element.width},0
-          L${element.width},${element.height}
-          L${element.width * 0.35},${element.height}
-          L${element.width * 0.35},${element.height * 0.625}
-          L${element.width * 0.183},${element.height * 0.625}
-          L${element.width * 0.183},${element.height * 0.75}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, leftArrowCallout)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        leftArrowCallout.setAttribute("stroke", element.borderColor || "#000")
-        leftArrowCallout.setAttribute("stroke-width", element.borderWidth || 1)
-        leftArrowCallout.setAttribute("stroke-linecap", "butt")
-        leftArrowCallout.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            leftArrowCallout.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            leftArrowCallout.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            leftArrowCallout.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(leftArrowCallout)
-      break
-    case "upArrowCallout":
-      const upArrowCallout = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      upArrowCallout.setAttribute(
-        "d",
-        `M0,${element.height * 0.35}
-          L${element.width * 0.41},${element.height * 0.35}
-          L${element.width * 0.41},${element.height * 0.25}
-          L${element.width * 0.32},${element.height * 0.25}
-          L${element.width * 0.5},0
-          L${element.width * 0.68},${element.height * 0.25}
-          L${element.width * 0.59},${element.height * 0.25}
-          L${element.width * 0.59},${element.height * 0.35}
-          L${element.width},${element.height * 0.35}
-          L${element.width},${element.height}
-          L0,${element.height}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, upArrowCallout)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        upArrowCallout.setAttribute("stroke", element.borderColor || "#000")
-        upArrowCallout.setAttribute("stroke-width", element.borderWidth || 1)
-        upArrowCallout.setAttribute("stroke-linecap", "butt")
-        upArrowCallout.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            upArrowCallout.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            upArrowCallout.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            upArrowCallout.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(upArrowCallout)
-      break
-    case "notchedRightArrow":
-      const notchedRightArrow = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      notchedRightArrow.setAttribute(
-        "d",
-        `M0,${element.height * 0.25}
-          L${element.width * 0.83},${element.height * 0.25}
-          L${element.width * 0.83},0
-          L${element.width},${element.height * 0.5}
-          L${element.width * 0.83},${element.height}
-          L${element.width * 0.83},${element.height * 0.75}
-          L0,${element.height * 0.75}
-          L${element.width * 0.086},${element.height * 0.5}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, notchedRightArrow)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        notchedRightArrow.setAttribute("stroke", element.borderColor || "#000")
-        notchedRightArrow.setAttribute("stroke-width", element.borderWidth || 1)
-        notchedRightArrow.setAttribute("stroke-linecap", "butt")
-        notchedRightArrow.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            notchedRightArrow.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            notchedRightArrow.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            notchedRightArrow.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(notchedRightArrow)
-      break
-    case "homePlate":
-      const homePlate = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      homePlate.setAttribute(
-        "d",
-        `M0,0
-          L${element.width * 0.925},0
-          L${element.width},${element.height * 0.5}
-          L${element.width * 0.925},${element.height}
-          L0,${element.height}
-          Z`
-      )
-
-      // 设置填充色
-      setBackground(element, homePlate)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        homePlate.setAttribute("stroke", element.borderColor || "#000")
-        homePlate.setAttribute("stroke-width", element.borderWidth || 1)
-        homePlate.setAttribute("stroke-linecap", "butt")
-        homePlate.setAttribute("stroke-linejoin", "round")
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            homePlate.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            homePlate.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            homePlate.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(homePlate)
-      break
-    case "rightTriangle":
-      const rightTriangle = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      rightTriangle.setAttribute(
-        "points",
-        `0,0 ${element.width},${element.height} 0,${element.height}`
-      )
-
-      // 设置填充色
-      setBackground(element, rightTriangle)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        rightTriangle.setAttribute("stroke", element.borderColor || "#000")
-        rightTriangle.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            rightTriangle.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            rightTriangle.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            rightTriangle.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(rightTriangle)
-      break
-    case "semiCircle":
-      const semiCircle = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      semiCircle.setAttribute(
-        "d",
-        `M0,${element.height} A${element.width / 2},${element.height} 0 0,1 ${
-          element.width
-        },${element.height} Z`
-      )
-
-      // 设置填充色
-      setBackground(element, semiCircle)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        semiCircle.setAttribute("stroke", element.borderColor || "#000")
-        semiCircle.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            semiCircle.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            semiCircle.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            semiCircle.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(semiCircle)
-      break
-
-    case "star":
-      const star = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      const cx = element.width / 2
-      const cy = element.height / 2
-      const outerRadius = Math.min(element.width, element.height) / 2
-      const innerRadius = outerRadius * 0.4
-      let starPoints = ""
-
-      for (let i = 0; i < 10; i++) {
-        const radius = i % 2 === 0 ? outerRadius : innerRadius
-        const angle = (Math.PI * i) / 5
-        const x = cx + radius * Math.sin(angle)
-        const y = cy - radius * Math.cos(angle)
-        starPoints += `${x},${y} `
-      }
-
-      star.setAttribute("points", starPoints.trim())
-
-      // 设置填充色
-      setBackground(element, star)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        star.setAttribute("stroke", element.borderColor || "#000")
-        star.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            star.setAttribute("stroke-dasharray", element.borderStrokeDasharray)
-          } else if (element.borderType === "dotted") {
-            star.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            star.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(star)
-      break
-
-    case "cross":
-      const cross = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-      cross.setAttribute(
-        "points",
-        `${element.width * 0.35},0 ${element.width * 0.65},0 ${
-          element.width * 0.65
-        },${element.height * 0.35} ` +
-          `${element.width},${element.height * 0.35} ${element.width},${
-            element.height * 0.65
-          } ` +
-          `${element.width * 0.65},${element.height * 0.65} ${
-            element.width * 0.65
-          },${element.height} ` +
-          `${element.width * 0.35},${element.height} ${element.width * 0.35},${
-            element.height * 0.65
-          } ` +
-          `0,${element.height * 0.65} 0,${element.height * 0.35} ${
-            element.width * 0.35
-          },${element.height * 0.35}`
-      )
-
-      // 设置填充色
-      setBackground(element, cross)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        cross.setAttribute("stroke", element.borderColor || "#000")
-        cross.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            cross.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            cross.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            cross.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(cross)
-      break
-
-    case "chevron":
-      const chevron = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "polygon"
-      )
-
-      chevron.setAttribute(
-        "points",
-        `${element.width * 0.5},0 ${element.width},${element.height * 0.5} ` +
-          `${element.width * 0.5},${element.height} ` +
-          `0,${element.height} ${element.width * 0.5},${
-            element.height * 0.5
-          } 0,0`
-      )
-
-      // 设置填充色
-      setBackground(element, chevron)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        chevron.setAttribute("stroke", element.borderColor || "#000")
-        chevron.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            chevron.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            chevron.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            chevron.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(chevron)
-      break
-
-    case "frame":
-      // 创建外框和内框
-      const outerRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "rect"
-      )
-      outerRect.setAttribute("x", 0)
-      outerRect.setAttribute("y", 0)
-      outerRect.setAttribute("width", element.width)
-      outerRect.setAttribute("height", element.height)
-
-      const innerRect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "rect"
-      )
-      const frameWidth = element.width / 10
-      innerRect.setAttribute("x", frameWidth)
-      innerRect.setAttribute("y", frameWidth)
-      innerRect.setAttribute("width", element.width - frameWidth * 2)
-      innerRect.setAttribute("height", element.height - frameWidth * 2)
-
-      // 设置填充色
-      setBackground(element, outerRect)
-      innerRect.setAttribute("fill", "white") // 内框为白色
-      // 设置边框
-      if (element.borderWidth > 0) {
-        outerRect.setAttribute("stroke", element.borderColor || "#000")
-        outerRect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            outerRect.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            outerRect.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            outerRect.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(outerRect)
-      svg.appendChild(innerRect)
-      break
-
-    case "cloud":
-      // 使用路径绘制云形
-      const cloud = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-      const w = element.width
-      const h = element.height
-
-      cloud.setAttribute(
-        "d",
-        `M${w * 0.2},${h * 0.6} ` +
-          `C${w * 0.05},${h * 0.6} ${w * 0.05},${h * 0.3} ${w * 0.2},${
-            h * 0.3
-          } ` +
-          `C${w * 0.2},${h * 0.1} ${w * 0.45},${h * 0.1} ${w * 0.5},${
-            h * 0.3
-          } ` +
-          `C${w * 0.55},${h * 0.1} ${w * 0.8},${h * 0.1} ${w * 0.8},${
-            h * 0.3
-          } ` +
-          `C${w * 0.95},${h * 0.3} ${w * 0.95},${h * 0.6} ${w * 0.8},${
-            h * 0.6
-          } ` +
-          `L${w * 0.2},${h * 0.6} Z`
-      )
-
-      // 设置填充色
-      setBackground(element, cloud)
-      // 设置边框
-      if (element.borderWidth > 0) {
-        cloud.setAttribute("stroke", element.borderColor || "#000")
-        cloud.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            cloud.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            cloud.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            cloud.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(cloud)
-      break
-    case "blockArc":
-      const blockArc = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "path"
-      )
-
-      // 计算弧形参数
-      const rx = element.width / 2
-      const ry = element.height / 2
-      const blockArcFmlaInnerR = element.formulas
-        ? Math.sqrt(element.formulas[2].split(" ")[1] / 100000) / 2
-        : 0.5
-      const innerRx = rx * (1 - blockArcFmlaInnerR)
-      const innerRy = ry * (1 - blockArcFmlaInnerR)
-      //   const angle = element.formulas ? element.formulas[1].split(" ")[1]/(100000*360) : 0.5
-      // 构建路径
-      const path2 = `
-              M 0,${ry}
-              A ${rx} ${ry} 0 1 1 ${element.width} ${ry}
-              L ${element.width - (rx - innerRx)},${ry}
-              A ${innerRx} ${innerRy} 0 1 0 ${rx - innerRx},${ry}
-              Z`
-
-      blockArc.setAttribute("d", path2.trim())
-
-      // 设置填充色
-      setBackground(element, blockArc)
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        blockArc.setAttribute("stroke", element.borderColor || "#000")
-        blockArc.setAttribute("stroke-width", element.borderWidth || 1)
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            blockArc.setAttribute(
-              "stroke-dasharray",
-              element.borderStrokeDasharray
-            )
-          } else if (element.borderType === "dotted") {
-            blockArc.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            blockArc.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(blockArc)
-      break
-
-    case "rect":
-    default:
-      const rect = document.createElementNS(
-        "http://www.w3.org/2000/svg",
-        "rect"
-      )
-      rect.setAttribute("x", 0)
-      rect.setAttribute("y", 0)
-      rect.setAttribute("width", element.width)
-      rect.setAttribute("height", element.height)
-      if (element.fill && element.fill.type) {
-        // 设置填充色
-        if (element.fill.type === "color") {
-          rect.setAttribute("fill", element.fill.value || "transparent")
-        } else if (element.fill.type === "gradient") {
-          // 渐变填充
-          const { colors, path, rot } = element.fill.value
-
-          if (colors && colors.length >= 2) {
-            const gradientType = path === "rect" ? "linear" : "radial"
-            const gradientAngle =
-              gradientType === "linear" ? (90 - (rot || 0)) % 360 : rot || 0
-
-            let gradientString = `${gradientType}-gradient(`
-            if (gradientType === "linear") {
-              gradientString += `${gradientAngle}deg, `
-            }
-
-            colors.forEach((color, i) => {
-              gradientString += `${color.color} ${color.pos}${
-                i < colors.length - 1 ? ", " : ""
-              }`
-            })
-            gradientString += ")"
-
-            // 创建渐变定义
-            const gradientDef = document.createElementNS(
-              "http://www.w3.org/2000/svg",
-              "defs"
-            )
-            const gradientEl = document.createElementNS(
-              "http://www.w3.org/2000/svg",
-              gradientType === "linear" ? "linearGradient" : "radialGradient"
-            )
-            const gradientId = `gradient-${Date.now()}-${Math.random()
-              .toString(36)
-              .substr(2, 9)}`
-            gradientEl.setAttribute("id", gradientId)
-
-            // 设置渐变属性
-            if (gradientType === "linear") {
-              gradientEl.setAttribute(
-                "gradientTransform",
-                `rotate(${gradientAngle})`
-              )
-            }
-
-            // 添加渐变色标
-            colors.forEach((color) => {
-              const stop = document.createElementNS(
-                "http://www.w3.org/2000/svg",
-                "stop"
-              )
-              stop.setAttribute("offset", color.pos)
-              stop.setAttribute("stop-color", color.color)
-              gradientEl.appendChild(stop)
-            })
-
-            gradientDef.appendChild(gradientEl)
-            svg.appendChild(gradientDef)
-
-            // 应用渐变
-            rect.setAttribute("fill", `url(#${gradientId})`)
-          }
-        } else if (element.fill.type === "image") {
-          // 创建图案填充
-          const pattern = document.createElementNS(
-            "http://www.w3.org/2000/svg",
-            "pattern"
-          )
-          const patternId = `pattern-${Date.now()}-${Math.random()
-            .toString(36)
-            .substr(2, 9)}`
-          pattern.setAttribute("id", patternId)
-          pattern.setAttribute("patternUnits", "userSpaceOnUse")
-          pattern.setAttribute("width", "100%")
-          pattern.setAttribute("height", "100%")
-
-          // 创建图片元素
-          const image = document.createElementNS(
-            "http://www.w3.org/2000/svg",
-            "image"
-          )
-          image.setAttribute("width", "100%")
-          image.setAttribute("height", "100%")
-          image.setAttribute("preserveAspectRatio", "xMidYMid slice")
-          image.setAttributeNS(
-            "http://www.w3.org/1999/xlink",
-            "href",
-            element.fill.value.picBase64
-          )
-
-          pattern.appendChild(image)
-
-          // 添加pattern到defs
-          const defs = document.createElementNS(
-            "http://www.w3.org/2000/svg",
-            "defs"
-          )
-          defs.appendChild(pattern)
-          svg.appendChild(defs)
-
-          // 应用图案填充
-          rect.setAttribute("fill", `url(#${patternId})`)
-        } else {
-          rect.setAttribute("fill", "transparent")
-        }
-      } else {
-        rect.setAttribute("fill", "#ffffff00")
-      }
-
-      // 设置边框
-      if (element.borderWidth > 0) {
-        rect.setAttribute("stroke", element.borderColor || "#000")
-        rect.setAttribute("stroke-width", element.borderWidth || 1)
-
-        // 处理虚线边框
-        if (
-          element.borderType === "dotted" ||
-          element.borderType === "dashed"
-        ) {
-          if (element.borderStrokeDasharray) {
-            rect.setAttribute("stroke-dasharray", element.borderStrokeDasharray)
-          } else if (element.borderType === "dotted") {
-            rect.setAttribute("stroke-dasharray", "1, 3")
-          } else if (element.borderType === "dashed") {
-            rect.setAttribute("stroke-dasharray", "5, 5")
-          }
-        }
-      }
-
-      svg.appendChild(rect)
-      break
-  }
-
-  const transformList = []
-  let rotateDeg = element.rotate || 0
-
-  if (element.isFlipV) {
-    transformList.push(`scaleY(-1)`)
-    rotateDeg = -rotateDeg // 垂直翻转时反转旋转方向
-  }
-
-  if (element.isFlipH) {
-    transformList.push(`scaleX(-1)`)
-    rotateDeg = -rotateDeg // 水平翻转时反转旋转方向
-  }
-
-  if (element.rotate) {
-    transformList.push(`rotate(${rotateDeg}deg)`)
-  }
-
-  if (transformList.length > 0) {
-    el.style.transform = transformList.join(" ")
-    el.style.transformOrigin = "center center"
-  }
-
-  el.appendChild(svg)
-
-  // 设置形状内容
-  if (element.content) {
-    const contentContainer = document.createElement("div")
-    contentContainer.innerHTML = convertPtToPxInContent(element.content)
-    contentContainer.style.position = "absolute"
-    contentContainer.style.width = element.width + "px"
-    contentContainer.style.height = element.height + "px"
-    contentContainer.style.top = "0px"
-    contentContainer.style.left = "0px"
-    contentContainer.style.display = "flex"
-    contentContainer.style.alignItems = "center"
-    contentContainer.style.justifyContent = "center"
-    contentContainer.style.zIndex = element.order
-    contentContainer.style.pointerEvents = "none"
-    const transformList = []
-    let rotateDeg = element.rotate || 0
-
-    if (element.isFlipV) {
-      transformList.push(`scaleY(-1)`)
-      rotateDeg = -rotateDeg // 垂直翻转时反转旋转方向
-    }
-
-    if (element.isFlipH) {
-      transformList.push(`scaleX(-1)`)
-      rotateDeg = -rotateDeg // 水平翻转时反转旋转方向
-    }
-
-    if (element.rotate) {
-      transformList.push(`rotate(${rotateDeg}deg)`)
-    }
-
-    if (transformList.length > 0) {
-      contentContainer.style.transform = transformList.join(" ")
-      contentContainer.style.transformOrigin = "center center"
-    }
-    el.appendChild(contentContainer)
-  }
-  return el
-}

+ 0 - 76
src/components/view_file/vendors/pptx/elements/smartArt.js

@@ -1,76 +0,0 @@
-/*
- * @Author: LiZhiWei
- * @Date: 2025-05-14 15:51:28
- * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-14 15:59:07
- * @Description:
- */
-import { convertPtToPxInContent } from '../utils/style'
-export function createDiagramElement (element) {
-  const el = document.createElement('div')
-  el.style.position = 'absolute'
-  el.style.top = element.top + 'px'
-  el.style.left = element.left + 'px'
-  el.style.width = element.width + 'px'
-  el.style.height = element.height + 'px'
-  el.style.zIndex = element.order
-  // 递归渲染SmartArt节点
-  const renderDiagramNode = (node) => {
-    const nodeEl = document.createElement('div')
-    nodeEl.style.position = 'absolute'
-    nodeEl.style.left = node.left + 'px'
-    nodeEl.style.top = node.top + 'px'
-    nodeEl.style.width = node.width + 'px'
-    nodeEl.style.height = node.height + 'px'
-
-    // 设置边框
-    if (node.borderWidth > 0) {
-      nodeEl.style.border = `${node.borderWidth}px ${node.borderType} ${node.borderColor}`
-      if (node.borderStrokeDasharray && node.borderStrokeDasharray !== '0') {
-        nodeEl.style.borderStyle = 'dashed'
-      }
-    }
-
-    // 设置背景填充
-    if (node.fill && node.fill.type === 'color') {
-      nodeEl.style.backgroundColor = node.fill.value
-    }
-
-    // 设置内容
-    if (node.content) {
-      nodeEl.innerHTML = convertPtToPxInContent(node.content)
-    }
-
-    // 设置垂直对齐
-    if (node.vAlign === 'mid') {
-      nodeEl.style.display = 'flex'
-      nodeEl.style.alignItems = 'center'
-      nodeEl.style.justifyContent = 'center'
-    }
-
-    // 设置翻转
-    const transforms = []
-    if (node.isFlipV) {
-      transforms.push('scaleY(-1)')
-    }
-    if (node.isFlipH) {
-      transforms.push('scaleX(-1)')
-    }
-    if (transforms.length > 0) {
-      nodeEl.style.transform = transforms.join(' ')
-    }
-
-    return nodeEl
-  }
-
-  // 按照 order 排序元素
-  const sortedElements = [...element.elements].sort((a, b) => a.order - b.order)
-
-  // 渲染所有节点
-  sortedElements.forEach((node) => {
-    const nodeEl = renderDiagramNode(node)
-    el.appendChild(nodeEl)
-  })
-
-  return el
-}

+ 0 - 136
src/components/view_file/vendors/pptx/elements/table.js

@@ -1,136 +0,0 @@
-import { convertPtToPxInContent } from '../utils/style'
-export function createTableElement (element) {
-  const el = document.createElement('div')
-  el.style.position = 'absolute'
-  el.style.top = element.top + 'px'
-  el.style.left = element.left + 'px'
-  el.style.width = element.width + 'px'
-  el.style.height = element.height + 'px'
-  el.style.zIndex = element.order
-
-  // 创建表格元素
-  const table = document.createElement('table')
-  table.style.width = element.width + 'px'
-  table.style.height = element.height + 'px'
-  table.style.borderCollapse = 'collapse'
-  table.style.tableLayout = 'fixed'
-  // 设置表格边框
-  if (element.borders) {
-    if (element.borders.all) {
-      const border = element.borders.all
-      table.style.border = `${border.borderWidth || 1}px ${border.borderType || 'solid'} ${
-        border.borderColor || '#000'
-      }`
-    } else {
-      // 分别设置四边边框
-      if (element.borders.top) {
-        table.style.borderTop = `${element.borders.top.borderWidth || 1}px ${
-          element.borders.top.borderType || 'solid'
-        } ${element.borders.top.borderColor || '#000'}`
-      }
-      if (element.borders.bottom) {
-        table.style.borderBottom = `${element.borders.bottom.borderWidth || 1}px ${
-          element.borders.bottom.borderType || 'solid'
-        } ${element.borders.bottom.borderColor || '#000'}`
-      }
-      if (element.borders.left) {
-        table.style.borderLeft = `${element.borders.left.borderWidth || 1}px ${
-          element.borders.left.borderType || 'solid'
-        } ${element.borders.left.borderColor || '#000'}`
-      }
-      if (element.borders.right) {
-        table.style.borderRight = `${element.borders.right.borderWidth || 1}px ${
-          element.borders.right.borderType || 'solid'
-        } ${element.borders.right.borderColor || '#000'}`
-      }
-    }
-  }
-
-  // 创建表格内容
-  const tbody = document.createElement('tbody')
-
-  // 处理表格数据
-  if (element.data && element.data.length > 0) {
-    element.data.forEach((rowData, rowIndex) => {
-      const tr = document.createElement('tr')
-
-      rowData.forEach((cell, colIndex) => {
-        // 跳过被合并的单元格
-        if (cell.hMerge) return
-
-        const td = document.createElement('td')
-
-        // 设置单元格内容
-        if (cell.text) {
-          td.innerHTML = convertPtToPxInContent(cell.text)
-        }
-
-        // 设置单元格样式
-        td.style.padding = '0px'
-        td.style.verticalAlign = 'middle'
-
-        // 设置文本样式
-        if (cell.fontColor) td.style.color = cell.fontColor
-        if (cell.fontSize) td.style.fontSize = cell.fontSize
-        if (cell.fontFamily) td.style.fontFamily = cell.fontFamily
-        if (cell.bold) td.style.fontWeight = 'bold'
-        if (cell.italic) td.style.fontStyle = 'italic'
-        if (cell.underline) td.style.textDecoration = 'underline'
-        if (cell.align) td.style.textAlign = cell.align
-
-        // 设置背景色
-        if (cell.fillColor) td.style.backgroundColor = cell.fillColor
-
-        // 设置单元格边框
-        if (cell.borders) {
-          if (cell.borders.all) {
-            const border = cell.borders.all
-            td.style.border = `${border.borderWidth || 1}px ${border.borderType || 'solid'} ${
-              border.borderColor || '#000'
-            }`
-          } else {
-            // 分别设置四边边框
-            if (cell.borders.top) {
-              td.style.borderTop = `${cell.borders.top.borderWidth || 1}px ${
-                cell.borders.top.borderType || 'solid'
-              } ${cell.borders.top.borderColor || '#000'}`
-            }
-            if (cell.borders.bottom) {
-              td.style.borderBottom = `${cell.borders.bottom.borderWidth || 1}px ${
-                cell.borders.bottom.borderType || 'solid'
-              } ${cell.borders.bottom.borderColor || '#000'}`
-            }
-            if (cell.borders.left) {
-              td.style.borderLeft = `${cell.borders.left.borderWidth || 1}px ${
-                cell.borders.left.borderType || 'solid'
-              } ${cell.borders.left.borderColor || '#000'}`
-            }
-            if (cell.borders.right) {
-              td.style.borderRight = `${cell.borders.right.borderWidth || 1}px ${
-                cell.borders.right.borderType || 'solid'
-              } ${cell.borders.right.borderColor || '#000'}`
-            }
-          }
-        }
-        td.style.width = element.colWidths[colIndex] + 'px'
-        // 设置单元格合并
-        if (cell.colSpan && cell.colSpan > 1) {
-          td.colSpan = cell.colSpan
-          td.style.width = element.colWidths[colIndex] * cell.colSpan + 'px'
-        }
-        if (cell.rowSpan && cell.rowSpan > 1) {
-          td.rowSpan = cell.rowSpan
-        }
-
-        tr.appendChild(td)
-      })
-      tr.style.height = element.rowHeights[rowIndex] + 'px'
-      tbody.appendChild(tr)
-    })
-  }
-
-  table.appendChild(tbody)
-  el.appendChild(table)
-
-  return el
-}

+ 0 - 55
src/components/view_file/vendors/pptx/elements/text.js

@@ -1,55 +0,0 @@
-/*
- * @Author: LiZhiWei
- * @Date: 2025-05-14 15:14:03
- * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-14 15:59:19
- * @Description:
- */
-import { convertPtToPxInContent } from '../utils/style'
-// 创建文本元素
-export function createTextElement (element) {
-  const el = document.createElement('div')
-  if (element.content) {
-    // 转换内容中的pt单位为px单位
-    const convertedContent = convertPtToPxInContent(element.content)
-    el.innerHTML = convertedContent
-
-    // 设置文本样式
-    el.style.width = element.width + 'px'
-    el.style.height = element.height + 'px'
-    el.style.color = element.fontColor || '#000'
-    el.style.fontSize = element.fontSize
-    el.style.fontFamily = element.fontFamily || 'Arial'
-    el.style.textAlign = element.align || 'left'
-    el.style.fontWeight = element.bold ? 'bold' : 'normal'
-    el.style.fontStyle = element.italic ? 'italic' : 'normal'
-    el.style.textDecoration = element.underline ? 'underline' : 'none'
-    el.style.position = 'absolute'
-    el.style.top = element.top + 'px' || '0'
-    el.style.left = element.left + 'px' || '0'
-    el.style.zIndex = element.order
-    el.style.whiteSpace = 'pre-wrap'
-
-    // 添加垂直对齐支持
-    el.style.display = 'flex'
-    el.style.flexDirection = 'column'
-    switch (element.vAlign) {
-      case 'up':
-        el.style.justifyContent = 'flex-start'
-        break
-      case 'mid':
-        el.style.justifyContent = 'center'
-        break
-      case 'down':
-        el.style.justifyContent = 'flex-end'
-        break
-      default:
-        el.style.justifyContent = 'flex-start'
-    }
-
-    // 设置段落间距
-    el.style.lineHeight = element.lineHeight + 'px' || '1.2'
-    el.style.letterSpacing = element.charSpacing ? `${element.charSpacing}px` : 'normal'
-  }
-  return el
-}

+ 0 - 12
src/components/view_file/vendors/pptx/elements/video.js

@@ -1,12 +0,0 @@
-export function createVideoElement (element) {
-  const el = document.createElement('video')
-  el.src = element.blob
-  el.controls = true
-  el.style.width = element.width + 'px'
-  el.style.height = element.height + 'px'
-  el.style.position = 'absolute'
-  el.style.top = element.top + 'px'
-  el.style.left = element.left + 'px'
-  el.style.zIndex = element.order
-  return el
-}

+ 310 - 0
src/components/view_file/vendors/pptx/index.d.ts

@@ -0,0 +1,310 @@
+export interface Shadow {
+  h: number
+  v: number
+  blur: number
+  color: string
+}
+
+export interface ColorFill {
+  type: 'color'
+  value: string
+}
+
+export interface ImageFill {
+  type: 'image'
+  value: {
+    picBase64: string
+    opacity: number
+  }
+}
+
+export interface GradientFill {
+  type: 'gradient'
+  value: {
+    path: 'line' | 'circle' | 'rect' | 'shape'
+    rot: number
+    colors: {
+      pos: string
+      color: string
+    }[]
+  }
+}
+
+export interface PatternFill {
+  type: 'pattern'
+  value: {
+    type: string
+    foregroundColor: string
+    backgroundColor: string
+  }
+}
+
+export type Fill = ColorFill | ImageFill | GradientFill | PatternFill
+
+export interface Border {
+  borderColor: string
+  borderWidth: number
+  borderType:'solid' | 'dashed' | 'dotted'
+}
+
+export interface AutoFit {
+  type: 'shape' | 'text'
+  fontScale?: number
+}
+
+export interface Shape {
+  type: 'shape'
+  left: number
+  top: number
+  width: number
+  height: number
+  borderColor: string
+  borderWidth: number
+  borderType: 'solid' | 'dashed' | 'dotted'
+  borderStrokeDasharray: string
+  shadow?: Shadow
+  fill: Fill
+  content: string
+  isFlipV: boolean
+  isFlipH: boolean
+  rotate: number
+  shapType: string
+  vAlign: string
+  path?: string
+  name: string
+  order: number
+  autoFit?: AutoFit
+}
+
+export interface Text {
+  type: 'text'
+  left: number
+  top: number
+  width: number
+  height: number
+  borderColor: string
+  borderWidth: number
+  borderType: 'solid' | 'dashed' | 'dotted'
+  borderStrokeDasharray: string
+  shadow?: Shadow
+  fill: Fill
+  isFlipV: boolean
+  isFlipH: boolean
+  isVertical: boolean
+  rotate: number
+  content: string
+  vAlign: string
+  name: string
+  order: number
+  autoFit?: AutoFit
+}
+
+export interface Image {
+  type: 'image'
+  left: number
+  top: number
+  width: number
+  height: number
+  src: string
+  rotate: number
+  isFlipH: boolean
+  isFlipV: boolean
+  order: number
+  rect?: {
+    t?: number
+    b?: number
+    l?: number
+    r?: number
+  }
+  geom: string
+  borderColor: string
+  borderWidth: number
+  borderType: 'solid' | 'dashed' | 'dotted'
+  borderStrokeDasharray: string
+  filters?: {
+    sharpen?: number
+    colorTemperature?: number
+    saturation?: number
+    brightness?: number
+    contrast?: number
+  }
+}
+
+export interface TableCell {
+  text: string
+  rowSpan?: number
+  colSpan?: number
+  vMerge?: number
+  hMerge?: number
+  fillColor?: string
+  fontColor?: string
+  fontBold?: boolean
+  borders: {
+    top?: Border
+    bottom?: Border
+    left?: Border
+    right?: Border
+  }
+}
+export interface Table {
+  type: 'table'
+  left: number
+  top: number
+  width: number
+  height: number
+  data: TableCell[][]
+  borders: {
+    top?: Border
+    bottom?: Border
+    left?: Border
+    right?: Border
+  }
+  order: number
+  rowHeights: number[]
+  colWidths: number[]
+}
+
+export type ChartType = 'lineChart' |
+  'line3DChart' |
+  'barChart' |
+  'bar3DChart' |
+  'pieChart' |
+  'pie3DChart' |
+  'doughnutChart' |
+  'areaChart' |
+  'area3DChart' |
+  'scatterChart' |
+  'bubbleChart' |
+  'radarChart' |
+  'surfaceChart' |
+  'surface3DChart' |
+  'stockChart'
+
+export interface ChartValue {
+  x: string
+  y: number
+}
+export interface ChartXLabel {
+  [key: string]: string
+}
+export interface ChartItem {
+  key: string
+  values: ChartValue[]
+  xlabels: ChartXLabel
+}
+export type ScatterChartData = [number[], number[]]
+export interface CommonChart {
+  type: 'chart'
+  left: number
+  top: number
+  width: number
+  height: number
+  data: ChartItem[]
+  colors: string[]
+  chartType: Exclude<ChartType, 'scatterChart' | 'bubbleChart'>
+  barDir?: 'bar' | 'col'
+  marker?: boolean
+  holeSize?: string
+  grouping?: string
+  style?: string
+  order: number
+}
+export interface ScatterChart {
+  type: 'chart'
+  left: number
+  top: number
+  width: number
+  height: number
+  data: ScatterChartData
+  colors: string[]
+  chartType: 'scatterChart' | 'bubbleChart'
+  order: number
+}
+export type Chart = CommonChart | ScatterChart
+
+export interface Video {
+  type: 'video'
+  left: number
+  top: number
+  width: number
+  height: number
+  blob?: string
+  src?: string
+  order: number
+}
+
+export interface Audio {
+  type: 'audio'
+  left: number
+  top: number
+  width: number
+  height: number
+  blob: string
+  order: number
+}
+
+export interface Diagram {
+  type: 'diagram'
+  left: number
+  top: number
+  width: number
+  height: number
+  elements: (Shape | Text)[]
+  order: number
+}
+
+export interface Math {
+  type: 'math'
+  left: number
+  top: number
+  width: number
+  height: number
+  latex: string
+  picBase64: string
+  order: number
+  text?: string
+}
+
+export type BaseElement = Shape | Text | Image | Table | Chart | Video | Audio | Diagram | Math
+
+export interface Group {
+  type: 'group'
+  left: number
+  top: number
+  width: number
+  height: number
+  rotate: number
+  elements: BaseElement[]
+  order: number
+  isFlipH: boolean
+  isFlipV: boolean
+}
+export type Element = BaseElement | Group
+
+export interface SlideTransition {
+  type: string
+  duration: number
+  direction: string | null
+}
+
+export interface Slide {
+  fill: Fill
+  elements: Element[]
+  layoutElements: Element[]
+  note: string
+  transition?: SlideTransition | null
+}
+
+export interface Options {
+  slideFactor?: number
+  fontsizeFactor?: number
+}
+
+export const parse: (file: ArrayBuffer, options?: Options) => Promise<{
+  slides: Slide[]
+  themeColors: string[]
+  size: {
+    width: number
+    height: number
+  }
+}>

+ 8 - 1
src/components/view_file/vendors/pptx/index.js

@@ -1,6 +1,13 @@
+/*
+ * @Author: LiZhiWei
+ * @Date: 2025-12-26 14:35:12
+ * @LastEditors: LiZhiWei
+ * @LastEditTime: 2025-12-26 16:22:48
+ * @Description: 
+ */
 import { createApp } from "vue"
 import PPT from "./PPT.vue"
-import { parse } from "wisdom-pptxtojson"
+import { parse } from "./pptxtojson.js"
 
 /**
  * 渲染ppt

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/components/view_file/vendors/pptx/index.js copy.map


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/components/view_file/vendors/pptx/index.umd.js


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/components/view_file/vendors/pptx/index.umd.js.map


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/components/view_file/vendors/pptx/pptxtojson.js


+ 0 - 27
src/components/view_file/vendors/pptx/utils/style.js

@@ -1,27 +0,0 @@
-/*
- * @Author: LiZhiWei
- * @Date: 2025-05-14 15:53:57
- * @LastEditors: LiZhiWei
- * @LastEditTime: 2025-05-14 15:53:59
- * @Description:
- */
-export function adjustBrightness (color, factor) {
-  if (color === 'transparent') return color
-  const hex = color.replace('#', '')
-  const r = Math.min(255, Math.round(parseInt(hex.substr(0, 2), 16) * factor))
-  const g = Math.min(255, Math.round(parseInt(hex.substr(2, 2), 16) * factor))
-  const b = Math.min(255, Math.round(parseInt(hex.substr(4, 2), 16) * factor))
-  return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b
-    .toString(16)
-    .padStart(2, '0')}`
-}
-
-export function convertPtToPxInContent (content) {
-  if (!content) return content
-  // 使用正则表达式查找并替换
-  return content.replace(/(\d+\.?\d*)(pt|PT)/g, (match, size) => {
-    // 将 pt 转换为 px(1pt ≈ 1.33333px)
-    const pxSize = size
-    return `${pxSize}px`
-  })
-}

+ 13 - 8
src/views/index.vue

@@ -52,7 +52,7 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive, onMounted } from "vue"
+import { ref } from "vue"
 import ViewFile from "@/components/view_file/index.vue"
 
 type file = {
@@ -69,7 +69,7 @@ const fileData = ref<file>({
 
 const fileUrl = ref("")
 const loading = ref(false)
-const selectedFile = ref(null)
+const selectedFile = ref<any>(null)
 const urlOptions = [
   {
     value:
@@ -132,7 +132,8 @@ const loadFileFromUrl = async () => {
     // 从文件名或内容类型确定文件类型
     let fileType = ""
     if (filename.includes(".")) {
-      fileType = filename.split(".").pop().toLowerCase()
+      const ext = filename.split(".").pop()
+      fileType = ext ? ext.toLowerCase() : ""
     } else if (contentType.includes("pdf")) {
       fileType = "pdf"
     } else if (contentType.includes("image")) {
@@ -146,25 +147,29 @@ const loadFileFromUrl = async () => {
       type: fileType,
       fileBuffer: buffer,
     }
-  } catch (error) {
+  } catch (error: unknown) {
+    const message = error instanceof Error ? error.message : String(error)
     console.error("加载文件失败:", error)
-    ElMessage.error("加载文件失败: " + error.message)
+    ElMessage.error("加载文件失败: " + message)
   } finally {
     loading.value = false
   }
 }
 
 // 处理本地文件上传
-const handleFileChange = (file) => {
+const handleFileChange = (file: any) => {
   if (!file) return
 
   selectedFile.value = file
 
   const reader = new FileReader()
   reader.onload = (e) => {
-    const buffer = e.target.result
+    const buffer = e.target?.result
     const filename = file.name
-    const fileType = filename.split(".").pop().toLowerCase()
+    const ext = filename.split(".").pop()
+    const fileType = ext ? ext.toLowerCase() : ""
+
+    if (!(buffer instanceof ArrayBuffer)) return
 
     fileData.value = {
       filename: filename,

+ 6 - 0
src/vite-env.d.ts

@@ -1 +1,7 @@
 /// <reference types="vite/client" />
+
+declare module "*.vue" {
+  import type { DefineComponent } from "vue"
+  const component: DefineComponent<{}, {}, any>
+  export default component
+}

+ 6 - 1
tsconfig.app.json

@@ -3,6 +3,11 @@
   "compilerOptions": {
     "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
 
+    "baseUrl": ".",
+    "paths": {
+      "@/*": ["src/*"]
+    },
+
     /* Linting */
     "strict": true,
     "noUnusedLocals": true,
@@ -10,5 +15,5 @@
     "noFallthroughCasesInSwitch": true,
     "noUncheckedSideEffectImports": true
   },
-  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
+  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts", "components.d.ts"]
 }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.