jvs-ppt-ui 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jvs-ppt-ui",
3
3
  "private": false,
4
- "version": "0.0.6",
4
+ "version": "0.0.7",
5
5
  "type": "module",
6
6
  "main": "./dist/lib/jvs-ppt-ui.umd.js",
7
7
  "module": "./dist/lib/jvs-ppt-ui.es.js",
package/src/App.vue CHANGED
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
3
  import PptEditor from './components/PptEditor.vue'
4
- import type { DeckData, PptEditorApi } from './types'
4
+ import type { DeckData, PptEditorApi, UploadResourceContext } from './types'
5
5
 
6
6
  const editorRef = ref<PptEditorApi | null>(null)
7
7
 
@@ -12,20 +12,42 @@ function handleSave(deck: DeckData) {
12
12
  function handleReady(api: PptEditorApi) {
13
13
  console.log('[JVS-PPT 独立运行模式] 编辑器初始化完成:', api)
14
14
  }
15
+
16
+ /**
17
+ * 模拟资源上传函数
18
+ * 覆盖场景:导入 PPTX/JSON、上传图片、视频、音频、剪贴板粘贴、占位符上传、背景上传等
19
+ */
20
+ async function handleCustomUpload(fileOrBlob: File | Blob, context: UploadResourceContext): Promise<string> {
21
+ console.log('[模拟自定义上传函数触发] 接收到待上传资源:', {
22
+ type: context.type, // 资源类型: 'image' | 'video' | 'audio'
23
+ source: context.source, // 触发来源: 'file-upload' | 'pptx-import' | 'json-import' | 'paste' | 'placeholder' | 'background'
24
+ filename: context.filename,
25
+ size: `${(fileOrBlob.size / 1024).toFixed(2)} KB`,
26
+ fileOrBlob
27
+ })
28
+
29
+ // 1. 模拟网络上传请求耗时
30
+ await new Promise(resolve => setTimeout(resolve, 300))
31
+
32
+ // 2. 实际业务生产代码范例:
33
+ // const formData = new FormData()
34
+ // formData.append('file', fileOrBlob, context.filename || `upload_${Date.now()}`)
35
+ // formData.append('type', context.type)
36
+ // const res = await fetch('/api/oss/upload', { method: 'POST', body: formData }).then(r => r.json())
37
+ // return res.data.url
38
+
39
+ // 3. 模拟环境:生成可正常渲染的地址作为模拟的服务器返回 URL
40
+ const mockServerUrl = URL.createObjectURL(fileOrBlob)
41
+ console.log(`[模拟上传成功] 已返回服务器文件地址:`, mockServerUrl)
42
+ return mockServerUrl
43
+ }
15
44
  </script>
16
45
 
17
46
  <template>
18
- <PptEditor
19
- ref="editorRef"
20
- :enable-mcp="true"
21
- :enable-ai="true"
22
- ai-api-url="/jvs-dam/api/ppt/ai-replace"
23
- :enable-material="true"
24
- material-tree-api-url="/jvs-dam/api/dam/material/tree"
25
- material-page-api-url="/jvs-dam/api/dam/material/page"
26
- material-api-url="/jvs-dam/api/dam/material/tree"
27
- material-save-api-url="/jvs-dam/api/dam/material/save"
28
- @save="handleSave"
29
- @ready="handleReady"
30
- />
47
+ <!-- :custom-upload="handleCustomUpload" -->
48
+ <PptEditor ref="editorRef" :custom-upload="handleCustomUpload" :enable-mcp="true" :enable-ai="true"
49
+ ai-api-url="/jvs-dam/api/ppt/ai-replace" :enable-material="true"
50
+ material-tree-api-url="/jvs-dam/api/dam/material/tree" material-page-api-url="/jvs-dam/api/dam/material/page"
51
+ material-api-url="/jvs-dam/api/dam/material/tree" material-save-api-url="/jvs-dam/api/dam/material/save"
52
+ @save="handleSave" @ready="handleReady" />
31
53
  </template>
@@ -3604,8 +3604,6 @@ function handleBorderMouseDown(e: MouseEvent, el: any) {
3604
3604
  }
3605
3605
 
3606
3606
  function handleElementDblClick(e: MouseEvent, el: any) {
3607
- // TODO(debug): 定位“双击元素却新建了文本框”的拦截层,问题定位后移除
3608
- console.info('[元素dblclick调试]', el?.id, el?.type)
3609
3607
  let target = el
3610
3608
  if (selectedElementIds.value.length > 0 && !selectedElementIds.value.includes(el.id)) {
3611
3609
  const activeSelectedEl = findSelectedElementUnderPoint(e.clientX, e.clientY)
@@ -4188,7 +4188,10 @@ const parsePPTXJSONData = (json: any, zipMeta?: any) => {
4188
4188
  const borderGrad = el.border?.gradient || el.outline?.gradient
4189
4189
  const outlineGrad = borderGrad ? normalizeGradientConfig(borderGrad) : undefined
4190
4190
 
4191
- const pattern: string | undefined = el.fill?.type === 'image' ? el.fill.value.base64 : undefined
4191
+ const fillVal = el.fill?.type === 'image' ? el.fill.value : null
4192
+ const pattern: string | undefined = fillVal
4193
+ ? (fillVal.blob || fillVal.base64 || fillVal.src || fillVal.url || (typeof fillVal === 'string' ? fillVal : undefined))
4194
+ : undefined
4192
4195
 
4193
4196
  const fill = typeof el.fill === 'string'
4194
4197
  ? (el.fill.trim() === '' ? 'none' : el.fill)
@@ -4254,6 +4257,9 @@ const parsePPTXJSONData = (json: any, zipMeta?: any) => {
4254
4257
  element.style.flipH = flipH
4255
4258
  element.style.flipV = flipV
4256
4259
  element.style.fill = fill
4260
+ if (pattern) {
4261
+ element.style.pattern = pattern
4262
+ }
4257
4263
  element.style.borderColor = el.borderColor || (el.outline?.color || 'transparent')
4258
4264
  element.style.borderWidth = el.borderWidth !== undefined ? `${+(el.borderWidth * ratio).toFixed(2)}px` : (el.outline?.width !== undefined ? `${el.outline.width}px` : '0px')
4259
4265
  element.style.borderStyle = el.borderType || (el.outline?.style || 'solid')
@@ -165,7 +165,7 @@ function getElementPattern(el: any): string | undefined {
165
165
  if (typeof val === 'string') {
166
166
  pattern = val
167
167
  } else if (val && typeof val === 'object') {
168
- pattern = val.base64 || val.ref || val.src || val.url || ''
168
+ pattern = val.blob || val.base64 || val.src || val.url || ''
169
169
  }
170
170
  }
171
171
  }
@@ -553,7 +553,7 @@ function getElementPattern(el: any): string | undefined {
553
553
  if (typeof val === 'string') {
554
554
  pattern = val
555
555
  } else if (val && typeof val === 'object') {
556
- pattern = val.base64 || val.ref || val.src || val.url || ''
556
+ pattern = val.blob || val.base64 || val.src || val.url || ''
557
557
  }
558
558
  }
559
559
  }
@@ -1499,7 +1499,7 @@ function getElementPattern(el: any): string | undefined {
1499
1499
  if (el.pattern || el.style?.pattern) return el.pattern || el.style?.pattern
1500
1500
  const rawFill = (el.style && el.style.fill !== undefined) ? el.style.fill : el.fill
1501
1501
  if (rawFill && typeof rawFill === 'object' && (rawFill.type === 'image' || rawFill.type === 'pattern')) {
1502
- return rawFill.value?.src || rawFill.value?.url || rawFill.value
1502
+ return rawFill.value?.blob || rawFill.value?.src || rawFill.value?.base64 || rawFill.value?.url || (typeof rawFill.value === 'string' ? rawFill.value : undefined)
1503
1503
  }
1504
1504
  return undefined
1505
1505
  }
@@ -346,8 +346,9 @@ async function handleVideoFileChange(e: Event) {
346
346
  })
347
347
  })
348
348
  if (url) {
349
- mediaUrl.value = url
350
- notify('已选择本地视频文件')
349
+ addElement('video', url)
350
+ mediaPopoverVisible.value = false
351
+ notify('已成功添加视频')
351
352
  }
352
353
  } catch (err: any) {
353
354
  console.error(err)
@@ -370,8 +371,9 @@ async function handleAudioFileChange(e: Event) {
370
371
  })
371
372
  })
372
373
  if (url) {
373
- mediaUrl.value = url
374
- notify('已选择本地音频文件')
374
+ addElement('audio', url)
375
+ mediaPopoverVisible.value = false
376
+ notify('已成功添加音频')
375
377
  }
376
378
  } catch (err: any) {
377
379
  console.error(err)
@@ -5269,7 +5269,7 @@ function extractPatternFromFill(el: any): string | undefined {
5269
5269
  if (typeof val === 'string') {
5270
5270
  pattern = val
5271
5271
  } else if (val && typeof val === 'object') {
5272
- pattern = val.base64 || val.ref || val.src || val.url || ''
5272
+ pattern = val.blob || val.base64 || val.src || val.url || ''
5273
5273
  }
5274
5274
  }
5275
5275
  }
@@ -8058,9 +8058,13 @@ async function uploadMediaResourcesInSlides(deckOrSlides: any): Promise<void> {
8058
8058
  const remote = await uploadMediaUrl(targetSrc, 'image', 'svg')
8059
8059
  el.src = remote
8060
8060
  }
8061
- } else if (el.type === 'shape' && el.pattern && shouldUpload(el.pattern)) {
8062
- const remote = await uploadMediaUrl(el.pattern, 'image', 'png')
8063
- el.pattern = remote
8061
+ } else if (el.type === 'shape') {
8062
+ const targetPattern = el.pattern || el.style?.pattern || (el.fill?.type === 'image' ? (el.fill.value?.blob || el.fill.value?.base64 || el.fill.value?.src) : undefined)
8063
+ if (targetPattern && shouldUpload(targetPattern)) {
8064
+ const remote = await uploadMediaUrl(targetPattern, 'image', 'png')
8065
+ el.pattern = remote
8066
+ if (el.style) el.style.pattern = remote
8067
+ }
8064
8068
  }
8065
8069
  }
8066
8070
 
@@ -186,7 +186,7 @@ export function getElementPattern(el: any): string | undefined {
186
186
  if (typeof val === 'string') {
187
187
  pattern = val
188
188
  } else if (val && typeof val === 'object') {
189
- pattern = val.base64 || val.ref || val.src || val.url || ''
189
+ pattern = val.blob || val.base64 || val.src || val.url || ''
190
190
  }
191
191
  }
192
192
  }