diff --git a/src/hooks/useExport.ts b/src/hooks/useExport.ts index e8920758..dc01a531 100644 --- a/src/hooks/useExport.ts +++ b/src/hooks/useExport.ts @@ -240,6 +240,7 @@ export default () => { angle: 45, } } + if (el.link) options.hyperlink = { url: el.link } pptxSlide.addText(textProps, options) } @@ -255,6 +256,7 @@ export default () => { if (el.flipV) options.flipV = el.flipV if (el.rotate) options.rotate = el.rotate if (el.clip && el.clip.shape === 'ellipse') options.rounding = true + if (el.link) options.hyperlink = { url: el.link } pptxSlide.addImage(options) } @@ -271,6 +273,7 @@ export default () => { h: el.height / 100, } if (el.rotate) options.rotate = el.rotate + if (el.link) options.hyperlink = { url: el.link } pptxSlide.addImage(options) } @@ -312,6 +315,8 @@ export default () => { angle: 45, } } + if (el.link) options.hyperlink = { url: el.link } + pptxSlide.addShape('custGeom' as pptxgen.ShapeType, options) } } diff --git a/src/hooks/useLink.ts b/src/hooks/useLink.ts new file mode 100644 index 00000000..734e57d2 --- /dev/null +++ b/src/hooks/useLink.ts @@ -0,0 +1,33 @@ +import { MutationTypes, useStore } from '@/store' +import { PPTElement } from '@/types/slides' +import useHistorySnapshot from '@/hooks/useHistorySnapshot' +import { message } from 'ant-design-vue' + +export default () => { + const store = useStore() + + const { addHistorySnapshot } = useHistorySnapshot() + + const setLink = (handleElement: PPTElement, link: string) => { + const linkRegExp = /^(https?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/ + if (!link || !linkRegExp.test(link)) { + message.error('不是正确的网页链接地址') + return false + } + const props = { link } + store.commit(MutationTypes.UPDATE_ELEMENT, { id: handleElement.id, props }) + addHistorySnapshot() + + return true + } + + const removeLink = (handleElement: PPTElement) => { + store.commit(MutationTypes.REMOVE_ELEMENT_PROPS, { id: handleElement.id, propName: 'link' }) + addHistorySnapshot() + } + + return { + setLink, + removeLink, + } +} \ No newline at end of file diff --git a/src/types/slides.ts b/src/types/slides.ts index bcfe82b6..e27eb04b 100644 --- a/src/types/slides.ts +++ b/src/types/slides.ts @@ -30,6 +30,7 @@ interface PPTBaseElement { groupId?: string; width: number; height: number; + link?: string; } export interface PPTTextElement extends PPTBaseElement { diff --git a/src/views/Editor/Canvas/EditableElement.vue b/src/views/Editor/Canvas/EditableElement.vue index 95772011..7d9d514b 100644 --- a/src/views/Editor/Canvas/EditableElement.vue +++ b/src/views/Editor/Canvas/EditableElement.vue @@ -57,6 +57,10 @@ export default defineComponent({ type: Function as PropType<(e: MouseEvent, element: PPTElement, canMove?: boolean) => void>, required: true, }, + openLinkDialog: { + type: Function as PropType<() => void>, + required: true, + }, }, setup(props) { const currentElementComponent = computed(() => { @@ -144,6 +148,10 @@ export default defineComponent({ ], }, { divider: true }, + { + text: '设置链接', + handler: props.openLinkDialog, + }, { text: props.elementInfo.groupId ? '取消组合' : '组合', subText: 'Ctrl + G', diff --git a/src/views/Editor/Canvas/LinkDialog.vue b/src/views/Editor/Canvas/LinkDialog.vue new file mode 100644 index 00000000..d3872d51 --- /dev/null +++ b/src/views/Editor/Canvas/LinkDialog.vue @@ -0,0 +1,59 @@ + + + + + \ No newline at end of file diff --git a/src/views/Editor/Canvas/Operate/LinkHandler.vue b/src/views/Editor/Canvas/Operate/LinkHandler.vue new file mode 100644 index 00000000..8996cd1a --- /dev/null +++ b/src/views/Editor/Canvas/Operate/LinkHandler.vue @@ -0,0 +1,67 @@ + + + + + \ No newline at end of file diff --git a/src/views/Editor/Canvas/Operate/index.vue b/src/views/Editor/Canvas/Operate/index.vue index 6aadf828..a22eb207 100644 --- a/src/views/Editor/Canvas/Operate/index.vue +++ b/src/views/Editor/Canvas/Operate/index.vue @@ -26,6 +26,13 @@ > {{elementIndexInAnimation + 1}} + + @@ -41,9 +48,13 @@ import ShapeElementOperate from './ShapeElementOperate.vue' import LineElementOperate from './LineElementOperate.vue' import ChartElementOperate from './ChartElementOperate.vue' import TableElementOperate from './TableElementOperate.vue' +import LinkHandler from './LinkHandler.vue' export default defineComponent({ name: 'operate', + components: { + LinkHandler, + }, props: { elementInfo: { type: Object as PropType, @@ -77,6 +88,10 @@ export default defineComponent({ type: Function as PropType<(e: MouseEvent, element: PPTElement, command: OperateLineHandler) => void>, required: true, }, + openLinkDialog: { + type: Function as PropType<() => void>, + required: true, + }, }, setup(props) { const store = useStore() @@ -134,6 +149,5 @@ export default defineComponent({ display: flex; justify-content: center; align-items: center; - margin-bottom: 3px; } \ No newline at end of file diff --git a/src/views/Editor/Canvas/index.vue b/src/views/Editor/Canvas/index.vue index b358ecd1..493fcdf5 100644 --- a/src/views/Editor/Canvas/index.vue +++ b/src/views/Editor/Canvas/index.vue @@ -43,6 +43,7 @@ :isMultiSelect="activeElementIdList.length > 1" :rotateElement="rotateElement" :scaleElement="scaleElement" + :openLinkDialog="openLinkDialog" :dragLineElement="dragLineElement" /> @@ -68,9 +69,20 @@ :elementIndex="index + 1" :isMultiSelect="activeElementIdList.length > 1" :selectElement="selectElement" + :openLinkDialog="openLinkDialog" /> + + + + @@ -108,6 +120,7 @@ import AlignmentLine from './AlignmentLine.vue' import ElementCreateSelection from './ElementCreateSelection.vue' import MultiSelectOperate from './Operate/MultiSelectOperate.vue' import Operate from './Operate/index.vue' +import LinkDialog from './LinkDialog.vue' export default defineComponent({ name: 'editor-canvas', @@ -119,6 +132,7 @@ export default defineComponent({ ElementCreateSelection, MultiSelectOperate, Operate, + LinkDialog, }, setup() { const store = useStore() @@ -133,6 +147,9 @@ export default defineComponent({ const viewportRef = ref() const alignmentLines = ref([]) + const linkDialogVisible = ref(false) + const openLinkDialog = () => linkDialogVisible.value = true + watch(handleElementId, () => { store.commit(MutationTypes.SET_ACTIVE_GROUP_ELEMENT_ID, '') }) @@ -249,12 +266,14 @@ export default defineComponent({ viewportStyles, canvasScale, mouseSelectionState, - handleClickBlankArea, - removeEditorAreaFocus, currentSlide, creatingElement, - insertElementFromCreateSelection, alignmentLines, + linkDialogVisible, + openLinkDialog, + handleClickBlankArea, + removeEditorAreaFocus, + insertElementFromCreateSelection, selectElement, rotateElement, scaleElement, diff --git a/src/views/Screen/ScreenElement.vue b/src/views/Screen/ScreenElement.vue index 7a93b1a9..2c9b09b5 100644 --- a/src/views/Screen/ScreenElement.vue +++ b/src/views/Screen/ScreenElement.vue @@ -1,6 +1,7 @@