فهرست منبع

Merge branch 'beta' of https://git.cocorobo.cn/jack/PPT into beta

jack 1 روز پیش
والد
کامیت
fe48472002

+ 20 - 3
src/components/CollapsibleToolbar/index.vue

@@ -126,8 +126,10 @@
 
 <script lang="ts" setup>
 import { ref } from 'vue'
+import { storeToRefs } from 'pinia'
 import useCreateElement from '@/hooks/useCreateElement'
 import useSlideHandler from '@/hooks/useSlideHandler'
+import { useSlidesStore } from '@/store'
 
 interface ContentItem {
   tool?: number
@@ -150,6 +152,9 @@ const isCollapsed = ref(props.defaultCollapsed)
 const activeSubmenu = ref<string | null>(null)
 const contentList = ref<ContentItem[]>([])
 
+const slidesStore = useSlidesStore()
+const { currentSlide } = storeToRefs(slidesStore)
+
 const { createFrameElement } = useCreateElement()
 const { createSlide } = useSlideHandler()
 
@@ -217,10 +222,22 @@ const insertContent = (item: ContentItem) => {
   createFrameElement(item.url, item.tool)
 }
 
-const addContent = (data: ContentItem) => {
+const addContent = (data: ContentItem, type: number) => {
   // contentList.value.push(data)
-  createSlide()
-  insertContent(data)
+  if (type === 2) {
+    const elements = currentSlide.value?.elements || []
+    const frameElement = elements.find((el: any) => el.type === 'frame' && (el.toolType === 45 || el.toolType === 15))
+    if (frameElement) {
+      slidesStore.updateElement({
+        id: frameElement.id,
+        props: { url: data.url }
+      })
+    }
+  }
+  else {
+    createSlide()
+    insertContent(data)
+  }
 }
 
 Object.assign(window, { addContent, loadContentList })

+ 1 - 0
src/store/slides.ts

@@ -207,6 +207,7 @@ export const useSlidesStore = defineStore('slides', {
     },
   
     updateElement(data: UpdateElementData) {
+      console.log('data', data)
       const { id, props, slideId } = data
       const elIdList = typeof id === 'string' ? [id] : id
 

+ 28 - 1
src/views/Editor/CanvasTool/index.vue

@@ -94,6 +94,7 @@
     </div>
 
     <div class="right-handler">
+      <div v-if="hasInteractiveTool" class="handler-item viewport-size edit-tool-btn" @click="editTool">编辑工具</div>
       <IconMinus class="handler-item viewport-size" v-tooltip="'画布缩小(Ctrl + -)'" @click="scaleCanvas('-')" />
       <Popover trigger="click" v-model:value="canvasScaleVisible">
         <template #content>
@@ -126,7 +127,7 @@
 <script lang="ts" setup>
 import { ref, computed } from 'vue'
 import { storeToRefs } from 'pinia'
-import { useMainStore, useSnapshotStore } from '@/store'
+import { useMainStore, useSnapshotStore, useSlidesStore } from '@/store'
 import { getImageDataURL } from '@/utils/image'
 import type { ShapePoolItem } from '@/configs/shapes'
 import type { LinePoolItem } from '@/configs/lines'
@@ -148,8 +149,10 @@ import Popover from '@/components/Popover.vue'
 import PopoverMenuItem from '@/components/PopoverMenuItem.vue'
 
 const mainStore = useMainStore()
+const slidesStore = useSlidesStore()
 const { creatingElement, creatingCustomShape, showSelectPanel, showSearchPanel, showNotesPanel } = storeToRefs(mainStore)
 const { canUndo, canRedo } = storeToRefs(useSnapshotStore())
+const { currentSlide } = storeToRefs(slidesStore)
 
 const getInitialViewMode = () => {
   const urlParams = new URLSearchParams(window.location.search)
@@ -166,6 +169,25 @@ const getInitialViewMode = () => {
 
 const viewMode = computed(() => getInitialViewMode())
 
+const hasInteractiveTool = computed(() => {
+  const elements = currentSlide.value?.elements || []
+  return elements.some((el: any) => el.type === 'frame' && (el.toolType === 45 || el.toolType === 15))
+})
+
+const editTool = () => {
+  const elements = currentSlide.value?.elements || []
+  const frameElement = elements.find((el: any) => el.type === 'frame' && (el.toolType === 45 || el.toolType === 15))
+  if (frameElement) {
+    const url = frameElement.url || ''
+    
+    interface ParentWindowWithToolList extends Window {
+      toolBtn?: (action: number, id: string) => void;
+    }
+    const parentWindow = window.parent as ParentWindowWithToolList
+    parentWindow?.toolBtn?.(0, url)
+  }
+}
+
 const { redo, undo } = useHistorySnapshot()
 
 const {
@@ -409,6 +431,11 @@ const toggleNotesPanel = () => {
   }
 }
 
+.edit-tool-btn{
+  color: #285cf5;
+  cursor: pointer;
+}
+
 @media screen and (width <= 1200px) {
   .right-handler .text {
     display: none;

+ 12 - 0
src/views/components/element/FrameElement/index.vue

@@ -30,6 +30,7 @@
         <!-- B站视频类型(type 75):使用 iframe -->
         <iframe 
           v-else-if="elementInfo.toolType === 75"
+          :key="'bilibili-' + iframeKey"
           :src="elementInfo.url"
           :width="elementInfo.width"
           :height="elementInfo.height"
@@ -40,6 +41,7 @@
         <!-- 其他类型:保持原有逻辑 -->
         <iframe 
           v-else-if="elementInfo.isHTML"
+          :key="'html-' + iframeKey"
           :srcdoc="elementInfo.url"
           :width="elementInfo.width"
           :height="elementInfo.height"
@@ -49,6 +51,7 @@
         ></iframe>
         <iframe 
           v-else
+          :key="'src-' + iframeKey"
           :src="elementInfo.url"
           :width="elementInfo.width"
           :height="elementInfo.height"
@@ -78,6 +81,7 @@ import { storeToRefs } from 'pinia'
 import { useMainStore } from '@/store'
 import type { PPTFrameElement } from '@/types/slides'
 import type { ContextmenuItem } from '@/components/Contextmenu/types'
+import { ref, watch } from 'vue'
 
 const props = defineProps({
   elementInfo: {
@@ -96,6 +100,14 @@ const props = defineProps({
 
 const { handleElementId } = storeToRefs(useMainStore())
 
+const iframeKey = ref(0)
+
+watch(() => props.elementInfo.url, (newUrl, oldUrl) => {
+  if (newUrl !== oldUrl) {
+    iframeKey.value++
+  }
+})
+
 const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => {
   e.stopPropagation()
   props.selectElement(e, props.elementInfo, canMove)