chore: 类型调整,支持 volar

This commit is contained in:
pipipi-pikachu 2022-06-06 12:51:15 +08:00
parent 652665a4ae
commit 8f0b272224
49 changed files with 214 additions and 200 deletions

View File

@ -67,6 +67,12 @@ module.exports = {
'no-console': isProduction ? 'error' : 'warn', 'no-console': isProduction ? 'error' : 'warn',
'no-debugger': isProduction ? 'error' : 'warn', 'no-debugger': isProduction ? 'error' : 'warn',
'@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/ban-types': ['error', {
'extendDefaults': true,
'types': {
'{}': false,
},
}],
}, },
overrides: [ overrides: [
{ {

View File

@ -73,7 +73,12 @@ import { FORMULA_LIST, SYMBOL_LIST } from '@/configs/latex'
import FormulaContent from './FormulaContent.vue' import FormulaContent from './FormulaContent.vue'
import SymbolContent from './SymbolContent.vue' import SymbolContent from './SymbolContent.vue'
const tabs = [ interface Tab {
label: string;
value: 'symbol' | 'formula';
}
const tabs: Tab[] = [
{ label: '常用符号', value: 'symbol' }, { label: '常用符号', value: 'symbol' },
{ label: '预置公式', value: 'formula' }, { label: '预置公式', value: 'formula' },
] ]
@ -93,7 +98,7 @@ export default defineComponent({
}, },
setup(props, { emit }) { setup(props, { emit }) {
const latex = ref('') const latex = ref('')
const toolbarState = ref('symbol') const toolbarState = ref<'symbol' | 'formula'>('symbol')
const textAreaRef = ref<HTMLTextAreaElement>() const textAreaRef = ref<HTMLTextAreaElement>()
const selectedSymbolKey = ref(SYMBOL_LIST[0].type) const selectedSymbolKey = ref(SYMBOL_LIST[0].type)

View File

@ -1,14 +1,15 @@
import { ShapePoolItem } from '@/configs/shapes' import { ShapePoolItem } from '@/configs/shapes'
import { LinePoolItem } from '@/configs/lines' import { LinePoolItem } from '@/configs/lines'
import { ImageClipDataRange } from './slides'
export const enum ElementOrderCommands { export enum ElementOrderCommands {
UP = 'up', UP = 'up',
DOWN = 'down', DOWN = 'down',
TOP = 'top', TOP = 'top',
BOTTOM = 'bottom', BOTTOM = 'bottom',
} }
export const enum ElementAlignCommands { export enum ElementAlignCommands {
TOP = 'top', TOP = 'top',
BOTTOM = 'bottom', BOTTOM = 'bottom',
LEFT = 'left', LEFT = 'left',
@ -62,13 +63,6 @@ export interface MultiSelectRange {
maxY: number; maxY: number;
} }
export type ImageClipDataRange = [[number, number], [number, number]]
export interface ImageClipData {
range: ImageClipDataRange;
path: string;
}
export interface ImageClipedEmitData { export interface ImageClipedEmitData {
range: ImageClipDataRange; range: ImageClipDataRange;
position: { position: {

View File

@ -191,6 +191,8 @@ export interface ImageElementFilters {
'opacity'?: string; 'opacity'?: string;
} }
export type ImageClipDataRange = [[number, number], [number, number]]
/** /**
* *
* *
@ -199,7 +201,7 @@ export interface ImageElementFilters {
* shape: 裁剪形状 configs/imageClip.ts CLIPPATHS * shape: 裁剪形状 configs/imageClip.ts CLIPPATHS
*/ */
export interface ImageElementClip { export interface ImageElementClip {
range: [[number, number], [number, number]]; range: ImageClipDataRange;
shape: string; shape: string;
} }

View File

@ -31,7 +31,7 @@
:link="elementInfo.link" :link="elementInfo.link"
:openLinkDialog="openLinkDialog" :openLinkDialog="openLinkDialog"
v-if="isActive && elementInfo.link" v-if="isActive && elementInfo.link"
@mousedown.stop @mousedown.stop=""
/> />
</div> </div>
</template> </template>

View File

@ -6,7 +6,7 @@ import { PPTElement } from '@/types/slides'
export default ( export default (
elementList: Ref<PPTElement[]>, elementList: Ref<PPTElement[]>,
moveElement: (e: MouseEvent, element: PPTElement) => void, moveElement: (e: MouseEvent | TouchEvent, element: PPTElement) => void,
) => { ) => {
const mainStore = useMainStore() const mainStore = useMainStore()
const { activeElementIdList, activeGroupElementId, handleElementId, editorAreaFocus } = storeToRefs(mainStore) const { activeElementIdList, activeGroupElementId, handleElementId, editorAreaFocus } = storeToRefs(mainStore)
@ -14,7 +14,7 @@ export default (
// 选中元素 // 选中元素
// startMove 表示是否需要再选中操作后进入到开始移动的状态 // startMove 表示是否需要再选中操作后进入到开始移动的状态
const selectElement = (e: MouseEvent, element: PPTElement, startMove = true) => { const selectElement = (e: MouseEvent | TouchEvent, element: PPTElement, startMove = true) => {
if (!editorAreaFocus.value) mainStore.setEditorareaFocus(true) if (!editorAreaFocus.value) mainStore.setEditorareaFocus(true)
// 如果目标元素当前未被选中,则将他设为选中状态 // 如果目标元素当前未被选中,则将他设为选中状态
@ -69,8 +69,8 @@ export default (
// 如果目标元素已被选中,同时也是当前操作元素,那么当目标元素在该状态下再次被点击时,将被设置为多选元素中的激活成员 // 如果目标元素已被选中,同时也是当前操作元素,那么当目标元素在该状态下再次被点击时,将被设置为多选元素中的激活成员
else if (activeGroupElementId.value !== element.id) { else if (activeGroupElementId.value !== element.id) {
const startPageX = e.pageX const startPageX = e instanceof TouchEvent ? e.changedTouches[0].pageX : e.pageX
const startPageY = e.pageY const startPageY = e instanceof TouchEvent ? e.changedTouches[0].pageY : e.pageY
;(e.target as HTMLElement).onmouseup = (e: MouseEvent) => { ;(e.target as HTMLElement).onmouseup = (e: MouseEvent) => {
const currentPageX = e.pageX const currentPageX = e.pageX

View File

@ -15,7 +15,7 @@
@click="activeTab = tab.key" @click="activeTab = tab.key"
>{{tab.label}}</div> >{{tab.label}}</div>
</div> </div>
<template v-for="key in Object.keys(animations)"> <template v-for="key in animationTypes">
<div :class="['animation-pool', key]" :key="key" v-if="activeTab === key"> <div :class="['animation-pool', key]" :key="key" v-if="activeTab === key">
<div class="pool-type" :key="effect.name" v-for="effect in animations[key]"> <div class="pool-type" :key="effect.name" v-for="effect in animations[key]">
<div class="type-title">{{effect.name}}</div> <div class="type-title">{{effect.name}}</div>
@ -87,7 +87,7 @@
:max="3000" :max="3000"
:step="500" :step="500"
:value="element.duration" :value="element.duration"
@change="value => updateElementAnimationDuration(element.id, value)" @change="value => updateElementAnimationDuration(element.id, value as number)"
style="flex: 5;" style="flex: 5;"
/> />
</div> </div>
@ -95,7 +95,7 @@
<div style="flex: 3;">触发方式</div> <div style="flex: 3;">触发方式</div>
<Select <Select
:value="element.trigger" :value="element.trigger"
@change="value => updateElementAnimationTrigger(element.id, value)" @change="value => updateElementAnimationTrigger(element.id, value as 'click' | 'meantime' | 'auto')"
style="flex: 5;" style="flex: 5;"
> >
<SelectOption value="click">主动触发</SelectOption> <SelectOption value="click">主动触发</SelectOption>
@ -155,6 +155,8 @@ interface TabItem {
label: string; label: string;
} }
const animationTypes: AnimationType[] = ['in', 'out', 'attention']
export default defineComponent({ export default defineComponent({
name: 'element-animation-panel', name: 'element-animation-panel',
components: { components: {
@ -341,6 +343,7 @@ export default defineComponent({
attention: ATTENTION_ANIMATIONS, attention: ATTENTION_ANIMATIONS,
}, },
prefix: ANIMATION_CLASS_PREFIX, prefix: ANIMATION_CLASS_PREFIX,
animationTypes,
addAnimation, addAnimation,
deleteAnimation, deleteAnimation,
handleDragEnd, handleDragEnd,

View File

@ -2,12 +2,12 @@
<div class="element-positopn-panel"> <div class="element-positopn-panel">
<div class="title">层级</div> <div class="title">层级</div>
<ButtonGroup class="row"> <ButtonGroup class="row">
<Button style="flex: 1;" @click="orderElement(handleElement, 'top')"><IconSendToBack class="btn-icon" /> 置于顶层</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.TOP)"><IconSendToBack class="btn-icon" /> 置于顶层</Button>
<Button style="flex: 1;" @click="orderElement(handleElement, 'bottom')"><IconBringToFrontOne class="btn-icon" /> 置于底层</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.BOTTOM)"><IconBringToFrontOne class="btn-icon" /> 置于底层</Button>
</ButtonGroup> </ButtonGroup>
<ButtonGroup class="row"> <ButtonGroup class="row">
<Button style="flex: 1;" @click="orderElement(handleElement, 'up')"><IconBringToFront class="btn-icon" /> 上移一层</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.UP)"><IconBringToFront class="btn-icon" /> 上移一层</Button>
<Button style="flex: 1;" @click="orderElement(handleElement, 'down')"><IconSentToBack class="btn-icon" /> 下移一层</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.DOWN)"><IconSentToBack class="btn-icon" /> 下移一层</Button>
</ButtonGroup> </ButtonGroup>
<Divider /> <Divider />
@ -15,24 +15,24 @@
<div class="title">对齐</div> <div class="title">对齐</div>
<ButtonGroup class="row"> <ButtonGroup class="row">
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="左对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="左对齐">
<Button style="flex: 1;" @click="alignElementToCanvas('left')"><IconAlignLeft /></Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.LEFT)"><IconAlignLeft /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="水平居中"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="水平居中">
<Button style="flex: 1;" @click="alignElementToCanvas('horizontal')"><IconAlignVertically /></Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.HORIZONTAL)"><IconAlignVertically /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="右对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="右对齐">
<Button style="flex: 1;" @click="alignElementToCanvas('right')"><IconAlignRight /></Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.RIGHT)"><IconAlignRight /></Button>
</Tooltip> </Tooltip>
</ButtonGroup> </ButtonGroup>
<ButtonGroup class="row"> <ButtonGroup class="row">
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="上对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="上对齐">
<Button style="flex: 1;" @click="alignElementToCanvas('top')"><IconAlignTop /></Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.TOP)"><IconAlignTop /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="垂直居中"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="垂直居中">
<Button style="flex: 1;" @click="alignElementToCanvas('vertical')"><IconAlignHorizontally /></Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.VERTICAL)"><IconAlignHorizontally /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="下对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="下对齐">
<Button style="flex: 1;" @click="alignElementToCanvas('bottom')"><IconAlignBottom /></Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.BOTTOM)"><IconAlignBottom /></Button>
</Tooltip> </Tooltip>
</ButtonGroup> </ButtonGroup>
@ -43,14 +43,14 @@
<InputNumber <InputNumber
:step="5" :step="5"
:value="left" :value="left"
@change="value => updateLeft(value)" @change="value => updateLeft(value as number)"
style="flex: 4;" style="flex: 4;"
/> />
<div style="flex: 1;"></div> <div style="flex: 1;"></div>
<InputNumber <InputNumber
:step="5" :step="5"
:value="top" :value="top"
@change="value => updateTop(value)" @change="value => updateTop(value as number)"
style="flex: 4;" style="flex: 4;"
/> />
</div> </div>
@ -69,7 +69,7 @@
:max="1500" :max="1500"
:step="5" :step="5"
:value="width" :value="width"
@change="value => updateWidth(value)" @change="value => updateWidth(value as number)"
style="flex: 4;" style="flex: 4;"
/> />
<template v-if="['image', 'shape', 'audio'].includes(handleElement.type)"> <template v-if="['image', 'shape', 'audio'].includes(handleElement.type)">
@ -87,7 +87,7 @@
:step="5" :step="5"
:disabled="handleElement.type === 'text'" :disabled="handleElement.type === 'text'"
:value="height" :value="height"
@change="value => updateHeight(value)" @change="value => updateHeight(value as number)"
style="flex: 4;" style="flex: 4;"
/> />
</div> </div>
@ -123,7 +123,7 @@
:max="180" :max="180"
:step="5" :step="5"
:value="rotate" :value="rotate"
@change="value => updateRotate(value)" @change="value => updateRotate(value as number)"
style="flex: 4;" style="flex: 4;"
/> />
</div> </div>
@ -132,10 +132,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, ref, watch } from 'vue' import { computed, defineComponent, Ref, ref, watch } from 'vue'
import { round } from 'lodash' import { round } from 'lodash'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { ElementAlignCommands, ElementOrderCommands } from '@/types/edit'
import { MIN_SIZE } from '@/configs/element' import { MIN_SIZE } from '@/configs/element'
import useOrderElement from '@/hooks/useOrderElement' import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas' import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
@ -230,7 +232,7 @@ export default defineComponent({
} }
return { return {
handleElement, handleElement: handleElement as Ref<PPTElement>,
orderElement, orderElement,
alignElementToCanvas, alignElementToCanvas,
left, left,
@ -247,6 +249,8 @@ export default defineComponent({
updateRotate, updateRotate,
updateFixedRatio, updateFixedRatio,
updateRotate45, updateRotate45,
ElementOrderCommands,
ElementAlignCommands,
} }
}, },
}) })

View File

@ -18,7 +18,7 @@
<div class="switch-wrapper" style="flex: 3;"> <div class="switch-wrapper" style="flex: 3;">
<Switch <Switch
:checked="handleElement.autoplay" :checked="handleElement.autoplay"
@change="checked => updateAudio({ autoplay: checked })" @change="checked => updateAudio({ autoplay: checked as boolean })"
/> />
</div> </div>
</div> </div>
@ -28,7 +28,7 @@
<div class="switch-wrapper" style="flex: 3;"> <div class="switch-wrapper" style="flex: 3;">
<Switch <Switch
:checked="handleElement.loop" :checked="handleElement.loop"
@change="checked => updateAudio({ loop: checked })" @change="checked => updateAudio({ loop: checked as boolean })"
/> />
</div> </div>
</div> </div>
@ -36,7 +36,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent, Ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTAudioElement } from '@/types/slides' import { PPTAudioElement } from '@/types/slides'
@ -62,7 +62,7 @@ export default defineComponent({
} }
return { return {
handleElement, handleElement: handleElement as Ref<PPTAudioElement>,
updateAudio, updateAudio,
} }
} }

View File

@ -47,7 +47,7 @@
<div class="row"> <div class="row">
<div style="flex: 2;">图例</div> <div style="flex: 2;">图例</div>
<Select style="flex: 3;" :value="legend" @change="value => updateLegend(value)"> <Select style="flex: 3;" :value="legend" @change="value => updateLegend(value as '' | 'top' | 'bottom')">
<SelectOption value="">不显示</SelectOption> <SelectOption value="">不显示</SelectOption>
<SelectOption value="top">显示在上方</SelectOption> <SelectOption value="top">显示在上方</SelectOption>
<SelectOption value="bottom">显示在下方</SelectOption> <SelectOption value="bottom">显示在下方</SelectOption>
@ -152,7 +152,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, onUnmounted, ref, watch } from 'vue' import { defineComponent, onUnmounted, Ref, ref, watch } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { ChartData, ChartOptions, PPTChartElement } from '@/types/slides' import { ChartData, ChartOptions, PPTChartElement } from '@/types/slides'
@ -197,7 +197,7 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()
const fill = ref<string>() const fill = ref<string>('#000')
const themeColor = ref<string[]>([]) const themeColor = ref<string[]>([])
const gridColor = ref('') const gridColor = ref('')
@ -313,7 +313,7 @@ export default defineComponent({
chartDataEditorVisible, chartDataEditorVisible,
presetThemesVisible, presetThemesVisible,
presetThemeColorHoverIndex, presetThemeColorHoverIndex,
handleElement, handleElement: handleElement as Ref<PPTChartElement>,
updateData, updateData,
fill, fill,
updateFill, updateFill,

View File

@ -58,7 +58,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue' import { defineComponent, Ref, ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTImageElement, SlideBackground } from '@/types/slides' import { PPTImageElement, SlideBackground } from '@/types/slides'
@ -265,7 +265,7 @@ export default defineComponent({
clipPanelVisible, clipPanelVisible,
shapeClipPathOptions, shapeClipPathOptions,
ratioClipOptions, ratioClipOptions,
handleElement, handleElement: handleElement as Ref<PPTImageElement>,
clipImage, clipImage,
presetImageClip, presetImageClip,
replaceImage, replaceImage,

View File

@ -22,7 +22,7 @@
:min="1" :min="1"
:max="3" :max="3"
:value="handleElement.strokeWidth" :value="handleElement.strokeWidth"
@change="value => updateLatex({ strokeWidth: value })" @change="value => updateLatex({ strokeWidth: value as number })"
style="flex: 3;" style="flex: 3;"
/> />
</div> </div>
@ -44,7 +44,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, onUnmounted, ref } from 'vue' import { defineComponent, onUnmounted, Ref, ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTLatexElement } from '@/types/slides' import { PPTLatexElement } from '@/types/slides'
@ -92,7 +92,7 @@ export default defineComponent({
}) })
return { return {
handleElement, handleElement: handleElement as Ref<PPTLatexElement>,
latexEditorVisible, latexEditorVisible,
updateLatex, updateLatex,
updateLatexData, updateLatexData,

View File

@ -5,7 +5,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="handleElement.style" :value="handleElement.style"
@change="value => updateLine({ style: value })" @change="value => updateLine({ style: value as 'solid' | 'dashed' })"
> >
<SelectOption value="solid">实线</SelectOption> <SelectOption value="solid">实线</SelectOption>
<SelectOption value="dashed">虚线</SelectOption> <SelectOption value="dashed">虚线</SelectOption>
@ -27,7 +27,7 @@
<div style="flex: 2;">线条宽度</div> <div style="flex: 2;">线条宽度</div>
<InputNumber <InputNumber
:value="handleElement.width" :value="handleElement.width"
@change="value => updateLine({ width: value })" @change="value => updateLine({ width: value as number })"
style="flex: 3;" style="flex: 3;"
/> />
</div> </div>
@ -37,7 +37,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="handleElement.points[0]" :value="handleElement.points[0]"
@change="value => updateLine({ points: [value, handleElement.points[1]] })" @change="value => updateLine({ points: [value as 'arrow' | 'dot', handleElement.points[1]] })"
> >
<SelectOption value=""></SelectOption> <SelectOption value=""></SelectOption>
<SelectOption value="arrow">箭头</SelectOption> <SelectOption value="arrow">箭头</SelectOption>
@ -49,7 +49,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="handleElement.points[1]" :value="handleElement.points[1]"
@change="value => updateLine({ points: [handleElement.points[0], value] })" @change="value => updateLine({ points: [handleElement.points[0], value as 'arrow' | 'dot'] })"
> >
<SelectOption value=""></SelectOption> <SelectOption value=""></SelectOption>
<SelectOption value="arrow">箭头</SelectOption> <SelectOption value="arrow">箭头</SelectOption>
@ -63,7 +63,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent, Ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTLineElement } from '@/types/slides' import { PPTLineElement } from '@/types/slides'
@ -91,7 +91,7 @@ export default defineComponent({
} }
return { return {
handleElement, handleElement: handleElement as Ref<PPTLineElement>,
updateLine, updateLine,
} }
} }

View File

@ -20,7 +20,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="outline.style" :value="outline.style"
@change="value => updateOutline({ style: value })" @change="value => updateOutline({ style: value as 'solid' | 'dashed' })"
> >
<SelectOption value="solid">实线边框</SelectOption> <SelectOption value="solid">实线边框</SelectOption>
<SelectOption value="dashed">虚线边框</SelectOption> <SelectOption value="dashed">虚线边框</SelectOption>
@ -35,14 +35,14 @@
@update:modelValue="value => updateOutline({ color: value })" @update:modelValue="value => updateOutline({ color: value })"
/> />
</template> </template>
<ColorButton :color="outline.color" style="flex: 3;" /> <ColorButton :color="outline.color || '#000'" style="flex: 3;" />
</Popover> </Popover>
</div> </div>
<div class="row"> <div class="row">
<div style="flex: 2;">边框粗细</div> <div style="flex: 2;">边框粗细</div>
<InputNumber <InputNumber
:value="outline.width" :value="outline.width"
@change="value => updateOutline({ width: value })" @change="value => updateOutline({ width: value as number })"
style="flex: 3;" style="flex: 3;"
/> />
</div> </div>
@ -53,7 +53,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="richTextAttrs.fontname" :value="richTextAttrs.fontname"
@change="value => updateFontStyle('fontname', value)" @change="value => updateFontStyle('fontname', value as string)"
> >
<template #suffixIcon><IconFontSize /></template> <template #suffixIcon><IconFontSize /></template>
<SelectOptGroup label="系统字体"> <SelectOptGroup label="系统字体">
@ -70,7 +70,7 @@
<Select <Select
style="flex: 2;" style="flex: 2;"
:value="richTextAttrs.fontsize" :value="richTextAttrs.fontsize"
@change="value => updateFontStyle('fontsize', value)" @change="value => updateFontStyle('fontsize', value as string)"
> >
<template #suffixIcon><IconAddText /></template> <template #suffixIcon><IconAddText /></template>
<SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize"> <SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize">

View File

@ -4,7 +4,7 @@
<Select <Select
style="flex: 10;" style="flex: 10;"
:value="fillType" :value="fillType"
@change="value => updateFillType(value)" @change="value => updateFillType(value as 'fill' | 'gradient')"
> >
<SelectOption value="fill">纯色填充</SelectOption> <SelectOption value="fill">纯色填充</SelectOption>
<SelectOption value="gradient">渐变填充</SelectOption> <SelectOption value="gradient">渐变填充</SelectOption>
@ -22,7 +22,7 @@
<Select <Select
style="flex: 10;" style="flex: 10;"
:value="gradient.type" :value="gradient.type"
@change="value => updateGradient({ type: value })" @change="value => updateGradient({ type: value as 'linear' | 'radial' })"
v-else v-else
> >
<SelectOption value="linear">线性渐变</SelectOption> <SelectOption value="linear">线性渐变</SelectOption>
@ -63,7 +63,7 @@
:max="360" :max="360"
:step="15" :step="15"
:value="gradient.rotate" :value="gradient.rotate"
@change="value => updateGradient({ rotate: value })" @change="value => updateGradient({ rotate: value as number })"
/> />
</div> </div>
</template> </template>
@ -76,7 +76,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="richTextAttrs.fontname" :value="richTextAttrs.fontname"
@change="value => emitRichTextCommand('fontname', value)" @change="value => emitRichTextCommand('fontname', value as string)"
> >
<template #suffixIcon><IconFontSize /></template> <template #suffixIcon><IconFontSize /></template>
<SelectOptGroup label="系统字体"> <SelectOptGroup label="系统字体">
@ -93,7 +93,7 @@
<Select <Select
style="flex: 2;" style="flex: 2;"
:value="richTextAttrs.fontsize" :value="richTextAttrs.fontsize"
@change="value => emitRichTextCommand('fontsize', value)" @change="value => emitRichTextCommand('fontsize', value as string)"
> >
<template #suffixIcon><IconAddText /></template> <template #suffixIcon><IconAddText /></template>
<SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize"> <SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize">
@ -223,7 +223,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, watch } from 'vue' import { defineComponent, Ref, ref, watch } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTShapeElement, ShapeGradient, ShapeText } from '@/types/slides' import { PPTShapeElement, ShapeGradient, ShapeText } from '@/types/slides'
@ -253,8 +253,12 @@ export default defineComponent({
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const { handleElement, handleElementId, richTextAttrs, availableFonts } = storeToRefs(mainStore) const { handleElement, handleElementId, richTextAttrs, availableFonts } = storeToRefs(mainStore)
const fill = ref<string>() const fill = ref<string>('#000')
const gradient = ref<ShapeGradient>() const gradient = ref<ShapeGradient>({
type: 'linear',
rotate: 0,
color: ['#fff', '#fff'],
})
const fillType = ref('fill') const fillType = ref('fill')
const textAlign = ref('middle') const textAlign = ref('middle')
@ -327,7 +331,7 @@ export default defineComponent({
availableFonts, availableFonts,
fontSizeOptions, fontSizeOptions,
webFonts, webFonts,
handleElement, handleElement: handleElement as Ref<PPTShapeElement>,
emitRichTextCommand, emitRichTextCommand,
updateFillType, updateFillType,
updateFill, updateFill,

View File

@ -4,7 +4,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="textAttrs.fontname" :value="textAttrs.fontname"
@change="value => updateTextAttrs({ fontname: value })" @change="value => updateTextAttrs({ fontname: value as string })"
> >
<template #suffixIcon><IconFontSize /></template> <template #suffixIcon><IconFontSize /></template>
<SelectOptGroup label="系统字体"> <SelectOptGroup label="系统字体">
@ -21,7 +21,7 @@
<Select <Select
style="flex: 2;" style="flex: 2;"
:value="textAttrs.fontsize" :value="textAttrs.fontsize"
@change="value => updateTextAttrs({ fontsize: value })" @change="value => updateTextAttrs({ fontsize: value as string })"
> >
<template #suffixIcon><IconAddText /></template> <template #suffixIcon><IconAddText /></template>
<SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize"> <SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize">
@ -139,12 +139,12 @@
<div class="switch-wrapper" style="flex: 3;"> <div class="switch-wrapper" style="flex: 3;">
<Switch <Switch
:checked="hasTheme" :checked="hasTheme"
@change="checked => toggleTheme(checked)" @change="checked => toggleTheme(checked as boolean)"
/> />
</div> </div>
</div> </div>
<template v-if="hasTheme"> <template v-if="theme">
<div class="row"> <div class="row">
<Checkbox <Checkbox
@change="e => updateTheme({ rowHeader: e.target.checked })" @change="e => updateTheme({ rowHeader: e.target.checked })"
@ -400,7 +400,6 @@ export default defineComponent({
} }
return { return {
handleElement,
availableFonts, availableFonts,
fontSizeOptions, fontSizeOptions,
textAttrs, textAttrs,

View File

@ -16,7 +16,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="richTextAttrs.fontname" :value="richTextAttrs.fontname"
@change="value => emitRichTextCommand('fontname', value)" @change="value => emitRichTextCommand('fontname', value as string)"
> >
<template #suffixIcon><IconFontSize /></template> <template #suffixIcon><IconFontSize /></template>
<SelectOptGroup label="系统字体"> <SelectOptGroup label="系统字体">
@ -33,7 +33,7 @@
<Select <Select
style="flex: 2;" style="flex: 2;"
:value="richTextAttrs.fontsize" :value="richTextAttrs.fontsize"
@change="value => emitRichTextCommand('fontsize', value)" @change="value => emitRichTextCommand('fontsize', value as string)"
> >
<template #suffixIcon><IconAddText /></template> <template #suffixIcon><IconAddText /></template>
<SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize"> <SelectOption v-for="fontsize in fontSizeOptions" :key="fontsize" :value="fontsize">
@ -222,28 +222,28 @@
<div class="row"> <div class="row">
<div style="flex: 2;">行间距</div> <div style="flex: 2;">行间距</div>
<Select style="flex: 3;" :value="lineHeight" @change="value => updateLineHeight(value)"> <Select style="flex: 3;" :value="lineHeight" @change="value => updateLineHeight(value as number)">
<template #suffixIcon><IconRowHeight /></template> <template #suffixIcon><IconRowHeight /></template>
<SelectOption v-for="item in lineHeightOptions" :key="item" :value="item">{{item}}</SelectOption> <SelectOption v-for="item in lineHeightOptions" :key="item" :value="item">{{item}}</SelectOption>
</Select> </Select>
</div> </div>
<div class="row"> <div class="row">
<div style="flex: 2;">段间距</div> <div style="flex: 2;">段间距</div>
<Select style="flex: 3;" :value="paragraphSpace" @change="value => updateParagraphSpace(value)"> <Select style="flex: 3;" :value="paragraphSpace" @change="value => updateParagraphSpace(value as number)">
<template #suffixIcon><IconVerticalSpacingBetweenItems /></template> <template #suffixIcon><IconVerticalSpacingBetweenItems /></template>
<SelectOption v-for="item in paragraphSpaceOptions" :key="item" :value="item">{{item}}px</SelectOption> <SelectOption v-for="item in paragraphSpaceOptions" :key="item" :value="item">{{item}}px</SelectOption>
</Select> </Select>
</div> </div>
<div class="row"> <div class="row">
<div style="flex: 2;">字间距</div> <div style="flex: 2;">字间距</div>
<Select style="flex: 3;" :value="wordSpace" @change="value => updateWordSpace(value)"> <Select style="flex: 3;" :value="wordSpace" @change="value => updateWordSpace(value as number)">
<template #suffixIcon><IconFullwidth /></template> <template #suffixIcon><IconFullwidth /></template>
<SelectOption v-for="item in wordSpaceOptions" :key="item" :value="item">{{item}}px</SelectOption> <SelectOption v-for="item in wordSpaceOptions" :key="item" :value="item">{{item}}px</SelectOption>
</Select> </Select>
</div> </div>
<div class="row"> <div class="row">
<div style="flex: 2;">首行缩进</div> <div style="flex: 2;">首行缩进</div>
<Select style="flex: 3;" :value="textIndent" @change="value => updateTextIndent(value)"> <Select style="flex: 3;" :value="textIndent" @change="value => updateTextIndent(value as number)">
<template #suffixIcon><IconIndentRight /></template> <template #suffixIcon><IconIndentRight /></template>
<SelectOption v-for="item in textIndentOptions" :key="item" :value="item">{{item}}px</SelectOption> <SelectOption v-for="item in textIndentOptions" :key="item" :value="item">{{item}}px</SelectOption>
</Select> </Select>
@ -379,7 +379,7 @@ export default defineComponent({
addHistorySnapshot() addHistorySnapshot()
} }
const fill = ref<string>() const fill = ref<string>('#000')
const lineHeight = ref<number>() const lineHeight = ref<number>()
const wordSpace = ref<number>() const wordSpace = ref<number>()
const textIndent = ref<number>() const textIndent = ref<number>()
@ -450,7 +450,7 @@ export default defineComponent({
link.value = richTextAttrs.value.link link.value = richTextAttrs.value.link
linkPopoverVisible.value = true linkPopoverVisible.value = true
} }
const updateLink = (link: string) => { const updateLink = (link?: string) => {
if (link) { if (link) {
const linkRegExp = /^(https?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/ const linkRegExp = /^(https?):\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*[\w\-@?^=%&\/~+#])?$/
if (!linkRegExp.test(link)) return message.error('不是正确的网页链接地址') if (!linkRegExp.test(link)) return message.error('不是正确的网页链接地址')

View File

@ -2,24 +2,24 @@
<div class="multi-position-panel"> <div class="multi-position-panel">
<ButtonGroup class="row"> <ButtonGroup class="row">
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="左对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="左对齐">
<Button style="flex: 1;" @click="alignElement('left')"><IconAlignLeft /></Button> <Button style="flex: 1;" @click="alignElement(ElementAlignCommands.LEFT)"><IconAlignLeft /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="水平居中"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="水平居中">
<Button style="flex: 1;" @click="alignElement('horizontal')"><IconAlignHorizontally /></Button> <Button style="flex: 1;" @click="alignElement(ElementAlignCommands.HORIZONTAL)"><IconAlignHorizontally /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="右对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="右对齐">
<Button style="flex: 1;" @click="alignElement('right')"><IconAlignRight /></Button> <Button style="flex: 1;" @click="alignElement(ElementAlignCommands.RIGHT)"><IconAlignRight /></Button>
</Tooltip> </Tooltip>
</ButtonGroup> </ButtonGroup>
<ButtonGroup class="row"> <ButtonGroup class="row">
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="上对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="上对齐">
<Button style="flex: 1;" @click="alignElement('top')"><IconAlignTop /></Button> <Button style="flex: 1;" @click="alignElement(ElementAlignCommands.TOP)"><IconAlignTop /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="垂直居中"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="垂直居中">
<Button style="flex: 1;" @click="alignElement('vertical')"><IconAlignVertically /></Button> <Button style="flex: 1;" @click="alignElement(ElementAlignCommands.VERTICAL)"><IconAlignVertically /></Button>
</Tooltip> </Tooltip>
<Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="下对齐"> <Tooltip :mouseLeaveDelay="0" :mouseEnterDelay="0.5" title="下对齐">
<Button style="flex: 1;" @click="alignElement('bottom')"><IconAlignBottom /></Button> <Button style="flex: 1;" @click="alignElement(ElementAlignCommands.BOTTOM)"><IconAlignBottom /></Button>
</Tooltip> </Tooltip>
</ButtonGroup> </ButtonGroup>
<ButtonGroup class="row" v-if="displayItemCount > 2"> <ButtonGroup class="row" v-if="displayItemCount > 2">
@ -68,6 +68,7 @@ export default defineComponent({
uniformHorizontalDisplay, uniformHorizontalDisplay,
uniformVerticalDisplay, uniformVerticalDisplay,
alignElement, alignElement,
ElementAlignCommands,
} }
}, },
}) })

View File

@ -5,7 +5,7 @@
<Select <Select
style="flex: 10;" style="flex: 10;"
:value="background.type" :value="background.type"
@change="value => updateBackgroundType(value)" @change="value => updateBackgroundType(value as 'gradient' | 'image' | 'solid')"
> >
<SelectOption value="solid">纯色填充</SelectOption> <SelectOption value="solid">纯色填充</SelectOption>
<SelectOption value="image">图片填充</SelectOption> <SelectOption value="image">图片填充</SelectOption>
@ -26,7 +26,7 @@
<Select <Select
style="flex: 10;" style="flex: 10;"
:value="background.imageSize || 'cover'" :value="background.imageSize || 'cover'"
@change="value => updateBackground({ imageSize: value })" @change="value => updateBackground({ imageSize: value as 'repeat' | 'cover' | 'contain' })"
v-else-if="background.type === 'image'" v-else-if="background.type === 'image'"
> >
<SelectOption value="contain">缩放</SelectOption> <SelectOption value="contain">缩放</SelectOption>
@ -37,7 +37,7 @@
<Select <Select
style="flex: 10;" style="flex: 10;"
:value="background.gradientType" :value="background.gradientType"
@change="value => updateBackground({ gradientType: value })" @change="value => updateBackground({ gradientType: value as 'linear' | 'radial' })"
v-else v-else
> >
<SelectOption value="linear">线性渐变</SelectOption> <SelectOption value="linear">线性渐变</SelectOption>
@ -61,11 +61,11 @@
<Popover trigger="click"> <Popover trigger="click">
<template #content> <template #content>
<ColorPicker <ColorPicker
:modelValue="background.gradientColor[0]" :modelValue="background.gradientColor![0]"
@update:modelValue="value => updateBackground({ gradientColor: [value, background.gradientColor[1]] })" @update:modelValue="value => updateBackground({ gradientColor: [value, background.gradientColor![1]] })"
/> />
</template> </template>
<ColorButton :color="background.gradientColor[0]" style="flex: 3;" /> <ColorButton :color="background.gradientColor![0]" style="flex: 3;" />
</Popover> </Popover>
</div> </div>
<div class="row"> <div class="row">
@ -73,11 +73,11 @@
<Popover trigger="click"> <Popover trigger="click">
<template #content> <template #content>
<ColorPicker <ColorPicker
:modelValue="background.gradientColor[1]" :modelValue="background.gradientColor![1]"
@update:modelValue="value => updateBackground({ gradientColor: [background.gradientColor[0], value] })" @update:modelValue="value => updateBackground({ gradientColor: [background.gradientColor![0], value] })"
/> />
</template> </template>
<ColorButton :color="background.gradientColor[1]" style="flex: 3;" /> <ColorButton :color="background.gradientColor![1]" style="flex: 3;" />
</Popover> </Popover>
</div> </div>
<div class="row" v-if="background.gradientType === 'linear'"> <div class="row" v-if="background.gradientType === 'linear'">
@ -88,7 +88,7 @@
:max="360" :max="360"
:step="15" :step="15"
:value="background.gradientRotate" :value="background.gradientRotate"
@change="value => updateBackground({ gradientRotate: value })" @change="value => updateBackground({ gradientRotate: value as number })"
/> />
</div> </div>
</div> </div>
@ -99,7 +99,7 @@
<div class="row"> <div class="row">
<div style="flex: 2;">画布尺寸</div> <div style="flex: 2;">画布尺寸</div>
<Select style="flex: 3;" :value="viewportRatio" @change="value => updateViewportRatio(value)"> <Select style="flex: 3;" :value="viewportRatio" @change="value => updateViewportRatio(value as number)">
<SelectOption :value="0.5625">宽屏 16 : 9</SelectOption> <SelectOption :value="0.5625">宽屏 16 : 9</SelectOption>
<SelectOption :value="0.625">宽屏 16 10</SelectOption> <SelectOption :value="0.625">宽屏 16 10</SelectOption>
<SelectOption :value="0.75">标准 4 3</SelectOption> <SelectOption :value="0.75">标准 4 3</SelectOption>
@ -114,7 +114,7 @@
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="theme.fontName" :value="theme.fontName"
@change="value => updateTheme({ fontName: value })" @change="value => updateTheme({ fontName: value as string })"
> >
<SelectOptGroup label="系统字体"> <SelectOptGroup label="系统字体">
<SelectOption v-for="font in availableFonts" :key="font.value" :value="font.value"> <SelectOption v-for="font in availableFonts" :key="font.value" :value="font.value">

View File

@ -5,7 +5,7 @@
<div class="switch-wrapper" style="flex: 3;"> <div class="switch-wrapper" style="flex: 3;">
<Switch <Switch
:checked="hasFilters" :checked="hasFilters"
@change="checked => toggleFilters(checked)" @change="checked => toggleFilters(checked as boolean)"
/> />
</div> </div>
</div> </div>
@ -18,7 +18,7 @@
:min="0" :min="0"
:step="filter.step" :step="filter.step"
:value="filter.value" :value="filter.value"
@change="value => updateFilter(filter, value)" @change="value => updateFilter(filter, value as number)"
/> />
</div> </div>
</div> </div>

View File

@ -8,7 +8,7 @@
:max="1" :max="1"
:step="0.1" :step="0.1"
:value="opacity" :value="opacity"
@change="value => updateOpacity(value)" @change="value => updateOpacity(value as number)"
/> />
</div> </div>
</div> </div>

View File

@ -5,17 +5,17 @@
<div class="switch-wrapper" style="flex: 3;"> <div class="switch-wrapper" style="flex: 3;">
<Switch <Switch
:checked="hasOutline" :checked="hasOutline"
@change="checked => toggleOutline(checked)" @change="checked => toggleOutline(checked as boolean)"
/> />
</div> </div>
</div> </div>
<template v-if="hasOutline"> <template v-if="hasOutline && outline">
<div class="row"> <div class="row">
<div style="flex: 2;">边框样式</div> <div style="flex: 2;">边框样式</div>
<Select <Select
style="flex: 3;" style="flex: 3;"
:value="outline.style" :value="outline.style"
@change="value => updateOutline({ style: value })" @change="value => updateOutline({ style: value as 'dashed' | 'solid' })"
> >
<SelectOption value="solid">实线边框</SelectOption> <SelectOption value="solid">实线边框</SelectOption>
<SelectOption value="dashed">虚线边框</SelectOption> <SelectOption value="dashed">虚线边框</SelectOption>
@ -30,14 +30,14 @@
@update:modelValue="value => updateOutline({ color: value })" @update:modelValue="value => updateOutline({ color: value })"
/> />
</template> </template>
<ColorButton :color="outline.color" style="flex: 3;" /> <ColorButton :color="outline.color || '#000'" style="flex: 3;" />
</Popover> </Popover>
</div> </div>
<div class="row"> <div class="row">
<div style="flex: 2;">边框粗细</div> <div style="flex: 2;">边框粗细</div>
<InputNumber <InputNumber
:value="outline.width" :value="outline.width"
@change="value => updateOutline({ width: value })" @change="value => updateOutline({ width: value as number })"
style="flex: 3;" style="flex: 3;"
/> />
</div> </div>

View File

@ -3,7 +3,7 @@
<div class="row"> <div class="row">
<div style="flex: 2;">启用阴影</div> <div style="flex: 2;">启用阴影</div>
<div class="switch-wrapper" style="flex: 3;"> <div class="switch-wrapper" style="flex: 3;">
<Switch :checked="hasShadow" @change="checked => toggleShadow(checked)" /> <Switch :checked="hasShadow" @change="checked => toggleShadow(checked as boolean)" />
</div> </div>
</div> </div>
<template v-if="hasShadow && shadow"> <template v-if="hasShadow && shadow">
@ -15,7 +15,7 @@
:max="10" :max="10"
:step="1" :step="1"
:value="shadow.h" :value="shadow.h"
@change="value => updateShadow({ h: value })" @change="value => updateShadow({ h: value as number })"
/> />
</div> </div>
<div class="row"> <div class="row">
@ -26,7 +26,7 @@
:max="10" :max="10"
:step="1" :step="1"
:value="shadow.v" :value="shadow.v"
@change="value => updateShadow({ v: value })" @change="value => updateShadow({ v: value as number })"
/> />
</div> </div>
<div class="row"> <div class="row">
@ -37,7 +37,7 @@
:max="20" :max="20"
:step="1" :step="1"
:value="shadow.blur" :value="shadow.blur"
@change="value => updateShadow({ blur: value })" @change="value => updateShadow({ blur: value as number })"
/> />
</div> </div>
<div class="row"> <div class="row">

View File

@ -96,23 +96,23 @@
<Divider style="margin: 20px 0;" /> <Divider style="margin: 20px 0;" />
<ButtonGroup class="row"> <ButtonGroup class="row">
<Button style="flex: 1;" @click="orderElement(handleElement, 'top')"><IconSendToBack class="icon" /> 置顶</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.TOP)"><IconSendToBack class="icon" /> 置顶</Button>
<Button style="flex: 1;" @click="orderElement(handleElement, 'bottom')"><IconBringToFrontOne class="icon" /> 置底</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.BOTTOM)"><IconBringToFrontOne class="icon" /> 置底</Button>
<Button style="flex: 1;" @click="orderElement(handleElement, 'up')"><IconBringToFront class="icon" /> 上移</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.UP)"><IconBringToFront class="icon" /> 上移</Button>
<Button style="flex: 1;" @click="orderElement(handleElement, 'down')"><IconSentToBack class="icon" /> 下移</Button> <Button style="flex: 1;" @click="orderElement(handleElement, ElementOrderCommands.DOWN)"><IconSentToBack class="icon" /> 下移</Button>
</ButtonGroup> </ButtonGroup>
<Divider style="margin: 20px 0;" /> <Divider style="margin: 20px 0;" />
<ButtonGroup class="row"> <ButtonGroup class="row">
<Button style="flex: 1;" @click="alignElementToCanvas('left')"><IconAlignLeft class="icon" /> 左对齐</Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.LEFT)"><IconAlignLeft class="icon" /> 左对齐</Button>
<Button style="flex: 1;" @click="alignElementToCanvas('horizontal')"><IconAlignVertically class="icon" /> 水平居中</Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.HORIZONTAL)"><IconAlignVertically class="icon" /> 水平居中</Button>
<Button style="flex: 1;" @click="alignElementToCanvas('right')"><IconAlignRight class="icon" /> 右对齐</Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.RIGHT)"><IconAlignRight class="icon" /> 右对齐</Button>
</ButtonGroup> </ButtonGroup>
<ButtonGroup class="row"> <ButtonGroup class="row">
<Button style="flex: 1;" @click="alignElementToCanvas('top')"><IconAlignTop class="icon" /> 上对齐</Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.TOP)"><IconAlignTop class="icon" /> 上对齐</Button>
<Button style="flex: 1;" @click="alignElementToCanvas('vertical')"><IconAlignHorizontally class="icon" /> 垂直居中</Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.VERTICAL)"><IconAlignHorizontally class="icon" /> 垂直居中</Button>
<Button style="flex: 1;" @click="alignElementToCanvas('bottom')"><IconAlignBottom class="icon" /> 下对齐</Button> <Button style="flex: 1;" @click="alignElementToCanvas(ElementAlignCommands.BOTTOM)"><IconAlignBottom class="icon" /> 下对齐</Button>
</ButtonGroup> </ButtonGroup>
</div> </div>
</div> </div>
@ -120,10 +120,11 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue' import { defineComponent, Ref, ref } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import { PPTElement, TableCell } from '@/types/slides' import { PPTElement, TableCell } from '@/types/slides'
import { ElementAlignCommands, ElementOrderCommands } from '@/types/edit'
import emitter, { EmitterEvents } from '@/utils/emitter' import emitter, { EmitterEvents } from '@/utils/emitter'
import useOrderElement from '@/hooks/useOrderElement' import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas' import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
@ -215,7 +216,7 @@ export default defineComponent({
} }
return { return {
handleElement, handleElement: handleElement as Ref<PPTElement>,
tabs, tabs,
activeTab, activeTab,
richTextAttrs, richTextAttrs,
@ -227,6 +228,8 @@ export default defineComponent({
emitRichTextCommand, emitRichTextCommand,
updateFontColor, updateFontColor,
updateFill, updateFill,
ElementOrderCommands,
ElementAlignCommands,
} }
}, },
}) })

View File

@ -40,7 +40,7 @@ export default defineComponent({
required: true, required: true,
}, },
selectElement: { selectElement: {
type: Function as PropType<(e: MouseEvent | TouchEvent, element: PPTElement, canMove?: boolean) => void>, type: Function as PropType<(e: TouchEvent, element: PPTElement, canMove?: boolean) => void>,
required: true, required: true,
}, },
}, },

View File

@ -5,10 +5,10 @@
top: elementInfo.top * canvasScale + 'px', top: elementInfo.top * canvasScale + 'px',
left: elementInfo.left * canvasScale + 'px', left: elementInfo.left * canvasScale + 'px',
transform: `rotate(${rotate}deg)`, transform: `rotate(${rotate}deg)`,
transformOrigin: `${elementInfo.width * canvasScale / 2}px ${height * canvasScale / 2}px`, transformOrigin: `${elementInfo.width * canvasScale / 2}px ${elementInfo.height * canvasScale / 2}px`,
}" }"
> >
<template v-if="isSelected && elementInfo.type !== 'line'"> <template v-if="isSelected">
<BorderLine <BorderLine
class="operate-border-line" class="operate-border-line"
v-for="line in borderLines" v-for="line in borderLines"
@ -32,7 +32,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType, computed } from 'vue' import { defineComponent, PropType, computed } from 'vue'
import { PPTElement, PPTLineElement } from '@/types/slides' import { PPTElement, PPTLineElement } from '@/types/slides'
import { getElementRange } from '@/utils/element'
import useCommonOperate from '@/views/Editor/Canvas/hooks/useCommonOperate' import useCommonOperate from '@/views/Editor/Canvas/hooks/useCommonOperate'
import { OperateResizeHandlers } from '@/types/edit' import { OperateResizeHandlers } from '@/types/edit'
@ -47,7 +46,7 @@ export default defineComponent({
}, },
props: { props: {
elementInfo: { elementInfo: {
type: Object as PropType<PPTElement>, type: Object as PropType<Exclude<PPTElement, PPTLineElement>>,
required: true, required: true,
}, },
isSelected: { isSelected: {
@ -65,23 +64,9 @@ export default defineComponent({
}, },
setup(props) { setup(props) {
const rotate = computed(() => 'rotate' in props.elementInfo ? props.elementInfo.rotate : 0) const rotate = computed(() => 'rotate' in props.elementInfo ? props.elementInfo.rotate : 0)
const width = computed(() => {
if (props.elementInfo.type === 'line') {
const { minX, maxX } = getElementRange(props.elementInfo)
return maxX - minX
}
return props.elementInfo.width
})
const height = computed(() => {
if (props.elementInfo.type === 'line') {
const { minY, maxY } = getElementRange(props.elementInfo)
return maxY - minY
}
return props.elementInfo.height
})
const scaleWidth = computed(() => width.value * props.canvasScale) const scaleWidth = computed(() => props.elementInfo.width * props.canvasScale)
const scaleHeight = computed(() => height.value * props.canvasScale) const scaleHeight = computed(() => props.elementInfo.height * props.canvasScale)
const { const {
borderLines, borderLines,
resizeHandlers, resizeHandlers,
@ -90,8 +75,6 @@ export default defineComponent({
return { return {
rotate, rotate,
width,
height,
borderLines, borderLines,
resizeHandlers: props.elementInfo.type === 'text' || props.elementInfo.type === 'table' ? textElementResizeHandlers : resizeHandlers, resizeHandlers: props.elementInfo.type === 'text' || props.elementInfo.type === 'table' ? textElementResizeHandlers : resizeHandlers,
} }

View File

@ -16,7 +16,7 @@
<ButtonGroup class="row"> <ButtonGroup class="row">
<Button style="flex: 1;" @click="insertTextElement()"><IconFontSize class="icon" /> 文字</Button> <Button style="flex: 1;" @click="insertTextElement()"><IconFontSize class="icon" /> 文字</Button>
<FileInput @change="files => insertImageElement(files)"> <FileInput @change="files => insertImageElement(files)">
<Button style="flex: 1;" @click="insertImageElement()"><IconPicture class="icon" /> 图片</Button> <Button style="flex: 1;"><IconPicture class="icon" /> 图片</Button>
</FileInput> </FileInput>
<Button style="flex: 1;" @click="insertShapeElement('square')"><IconSquare class="icon" /> 矩形</Button> <Button style="flex: 1;" @click="insertShapeElement('square')"><IconSquare class="icon" /> 矩形</Button>
<Button style="flex: 1;" @click="insertShapeElement('round')"><IconRound class="icon" /> 圆形</Button> <Button style="flex: 1;" @click="insertShapeElement('round')"><IconRound class="icon" /> 圆形</Button>

View File

@ -13,14 +13,15 @@
:length="line.length" :length="line.length"
:canvasScale="canvasScale" :canvasScale="canvasScale"
/> />
<template v-for="element in elementList" :key="element.id">
<MobileOperate <MobileOperate
v-for="element in elementList" v-if="element.type !== 'line'"
:key="element.id"
:elementInfo="element" :elementInfo="element"
:isSelected="activeElementIdList.includes(element.id)" :isSelected="activeElementIdList.includes(element.id)"
:canvasScale="canvasScale" :canvasScale="canvasScale"
:scaleElement="scaleElement" :scaleElement="scaleElement"
/> />
</template>
<div class="viewport" :style="{ transform: `scale(${canvasScale})` }"> <div class="viewport" :style="{ transform: `scale(${canvasScale})` }">
<MobileEditableElement <MobileEditableElement
v-for="(element, index) in elementList" v-for="(element, index) in elementList"

View File

@ -34,8 +34,8 @@
</div> </div>
<div <div
class="volume-bar-wrap" class="volume-bar-wrap"
@mousedown="$event => handleMousedownVolumeBar($event)" @mousedown="handleMousedownVolumeBar()"
@touchstart="$event => handleMousedownVolumeBar($event)" @touchstart="handleMousedownVolumeBar()"
@click="$event => handleClickVolumeBar($event)" @click="$event => handleClickVolumeBar($event)"
> >
<div class="volume-bar" ref="volumeBarRef"> <div class="volume-bar" ref="volumeBarRef">
@ -54,8 +54,8 @@
<div <div
class="bar-wrap" class="bar-wrap"
ref="playBarWrap" ref="playBarWrap"
@mousedown="$event => handleMousedownPlayBar($event)" @mousedown="handleMousedownPlayBar()"
@touchstart="$event => handleMousedownPlayBar($event)" @touchstart="handleMousedownPlayBar()"
@mousemove="$event => handleMousemovePlayBar($event)" @mousemove="$event => handleMousemovePlayBar($event)"
@mouseenter="playBarTimeVisible = true" @mouseenter="playBarTimeVisible = true"
@mouseleave="playBarTimeVisible = false" @mouseleave="playBarTimeVisible = false"

View File

@ -32,7 +32,7 @@
:src="elementInfo.src" :src="elementInfo.src"
:loop="elementInfo.loop" :loop="elementInfo.loop"
:scale="canvasScale" :scale="canvasScale"
@mousedown.stop @mousedown.stop=""
/> />
</div> </div>
</div> </div>
@ -98,7 +98,7 @@ export default defineComponent({
} }
}) })
const handleSelectElement = (e: MouseEvent) => { const handleSelectElement = (e: MouseEvent | TouchEvent) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -72,7 +72,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const handleSelectElement = (e: MouseEvent) => { const handleSelectElement = (e: MouseEvent | TouchEvent) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -35,7 +35,7 @@
> >
<div <div
:class="['clip-point', point, rotateClassName]" :class="['clip-point', point, rotateClassName]"
v-for="point in ['left-top', 'right-top', 'left-bottom', 'right-bottom']" v-for="point in cornerPoint"
:key="point" :key="point"
@mousedown.stop="$event => scaleClipRange($event, point)" @mousedown.stop="$event => scaleClipRange($event, point)"
> >
@ -49,7 +49,7 @@
</div> </div>
<div <div
:class="['clip-point', point, rotateClassName]" :class="['clip-point', point, rotateClassName]"
v-for="point in ['top', 'bottom', 'left', 'right']" v-for="point in edgePoints"
:key="point" :key="point"
@mousedown.stop="$event => scaleClipRange($event, point)" @mousedown.stop="$event => scaleClipRange($event, point)"
> >
@ -70,7 +70,8 @@ import { computed, defineComponent, onMounted, onUnmounted, PropType, ref } from
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useKeyboardStore } from '@/store' import { useMainStore, useKeyboardStore } from '@/store'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import { ImageClipData, ImageClipDataRange, ImageClipedEmitData, OperateResizeHandlers } from '@/types/edit' import { ImageClipedEmitData, OperateResizeHandlers } from '@/types/edit'
import { ImageClipDataRange, ImageElementClip } from '@/types/slides'
export default defineComponent({ export default defineComponent({
name: 'image-clip-handler', name: 'image-clip-handler',
@ -81,7 +82,7 @@ export default defineComponent({
required: true, required: true,
}, },
clipData: { clipData: {
type: Object as PropType<ImageClipData>, type: Object as PropType<ImageElementClip>,
}, },
clipPath: { clipPath: {
type: String, type: String,
@ -527,12 +528,27 @@ export default defineComponent({
return prefix + 0 return prefix + 0
}) })
const cornerPoint = [
OperateResizeHandlers.LEFT_TOP,
OperateResizeHandlers.RIGHT_TOP,
OperateResizeHandlers.LEFT_BOTTOM,
OperateResizeHandlers.RIGHT_BOTTOM,
]
const edgePoints = [
OperateResizeHandlers.TOP,
OperateResizeHandlers.BOTTOM,
OperateResizeHandlers.LEFT,
OperateResizeHandlers.RIGHT,
]
return { return {
clipWrapperPositionStyle, clipWrapperPositionStyle,
bottomImgPositionStyle, bottomImgPositionStyle,
topImgWrapperPositionStyle, topImgWrapperPositionStyle,
topImgPositionStyle, topImgPositionStyle,
rotateClassName, rotateClassName,
edgePoints,
cornerPoint,
handleClip, handleClip,
moveClipRange, moveClipRange,
scaleClipRange, scaleClipRange,

View File

@ -10,7 +10,6 @@
vector-effect="non-scaling-stroke" vector-effect="non-scaling-stroke"
stroke-linecap="butt" stroke-linecap="butt"
stroke-miterlimit="8" stroke-miterlimit="8"
stroke-linejoin
fill="transparent" fill="transparent"
:cx="width / 2" :cx="width / 2"
:cy="height / 2" :cy="height / 2"

View File

@ -10,7 +10,6 @@
vector-effect="non-scaling-stroke" vector-effect="non-scaling-stroke"
stroke-linecap="butt" stroke-linecap="butt"
stroke-miterlimit="8" stroke-miterlimit="8"
stroke-linejoin
fill="transparent" fill="transparent"
:d="createPath(width, height)" :d="createPath(width, height)"
:stroke="outlineColor" :stroke="outlineColor"

View File

@ -10,7 +10,6 @@
vector-effect="non-scaling-stroke" vector-effect="non-scaling-stroke"
stroke-linecap="butt" stroke-linecap="butt"
stroke-miterlimit="8" stroke-miterlimit="8"
stroke-linejoin
fill="transparent" fill="transparent"
:rx="radius" :rx="radius"
:ry="radius" :ry="radius"

View File

@ -115,7 +115,7 @@ export default defineComponent({
const filters = computed(() => props.elementInfo.filters) const filters = computed(() => props.elementInfo.filters)
const { filter } = useFilter(filters) const { filter } = useFilter(filters)
const handleSelectElement = (e: MouseEvent) => { const handleSelectElement = (e: MouseEvent | TouchEvent) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()
props.selectElement(e, props.elementInfo) props.selectElement(e, props.elementInfo)

View File

@ -63,7 +63,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const handleSelectElement = (e: MouseEvent) => { const handleSelectElement = (e: MouseEvent | TouchEvent) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -39,9 +39,6 @@
:stroke-width="elementInfo.width" :stroke-width="elementInfo.width"
:stroke-dasharray="lineDashArray" :stroke-dasharray="lineDashArray"
fill="none" fill="none"
stroke-linecap
stroke-linejoin
stroke-miterlimit
:marker-start="elementInfo.points[0] ? `url(#${elementInfo.id}-${elementInfo.points[0]}-start)` : ''" :marker-start="elementInfo.points[0] ? `url(#${elementInfo.id}-${elementInfo.points[0]}-start)` : ''"
:marker-end="elementInfo.points[1] ? `url(#${elementInfo.id}-${elementInfo.points[1]}-end)` : ''" :marker-end="elementInfo.points[1] ? `url(#${elementInfo.id}-${elementInfo.points[1]}-end)` : ''"
></path> ></path>

View File

@ -43,9 +43,6 @@
:stroke-width="elementInfo.width" :stroke-width="elementInfo.width"
:stroke-dasharray="lineDashArray" :stroke-dasharray="lineDashArray"
fill="none" fill="none"
stroke-linecap
stroke-linejoin
stroke-miterlimit
:marker-start="elementInfo.points[0] ? `url(#${elementInfo.id}-${elementInfo.points[0]}-start)` : ''" :marker-start="elementInfo.points[0] ? `url(#${elementInfo.id}-${elementInfo.points[0]}-start)` : ''"
:marker-end="elementInfo.points[1] ? `url(#${elementInfo.id}-${elementInfo.points[1]}-end)` : ''" :marker-end="elementInfo.points[1] ? `url(#${elementInfo.id}-${elementInfo.points[1]}-end)` : ''"
></path> ></path>
@ -90,7 +87,7 @@ export default defineComponent({
}, },
}, },
setup(props) { setup(props) {
const handleSelectElement = (e: MouseEvent) => { const handleSelectElement = (e: MouseEvent | TouchEvent) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -43,7 +43,6 @@
vector-effect="non-scaling-stroke" vector-effect="non-scaling-stroke"
stroke-linecap="butt" stroke-linecap="butt"
stroke-miterlimit="8" stroke-miterlimit="8"
stroke-linejoin=""
:d="elementInfo.path" :d="elementInfo.path"
:fill="elementInfo.gradient ? `url(#base-gradient-${elementInfo.id})` : elementInfo.fill" :fill="elementInfo.gradient ? `url(#base-gradient-${elementInfo.id})` : elementInfo.fill"
:stroke="outlineColor" :stroke="outlineColor"

View File

@ -49,7 +49,6 @@
vector-effect="non-scaling-stroke" vector-effect="non-scaling-stroke"
stroke-linecap="butt" stroke-linecap="butt"
stroke-miterlimit="8" stroke-miterlimit="8"
stroke-linejoin=""
:d="elementInfo.path" :d="elementInfo.path"
:fill="elementInfo.gradient ? `url(#editabel-gradient-${elementInfo.id})` : elementInfo.fill" :fill="elementInfo.gradient ? `url(#editabel-gradient-${elementInfo.id})` : elementInfo.fill"
:stroke="outlineColor" :stroke="outlineColor"
@ -119,7 +118,7 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()
const handleSelectElement = (e: MouseEvent, canMove = true) => { const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -2,10 +2,9 @@
<div <div
class="custom-textarea" class="custom-textarea"
ref="textareaRef" ref="textareaRef"
:contenteditable="contenteditable"
@focus="handleFocus" @focus="handleFocus"
@blur="handleBlur" @blur="handleBlur"
@input="$event => handleInput($event)" @input="handleInput()"
v-html="text" v-html="text"
></div> ></div>
</template> </template>
@ -102,5 +101,7 @@ export default defineComponent({
.custom-textarea { .custom-textarea {
border: 0; border: 0;
outline: 0; outline: 0;
-webkit-user-modify: read-write-plaintext-only;
-moz-user-modify: read-write-plaintext-only;
} }
</style> </style>

View File

@ -47,13 +47,12 @@
v-show="!hideCells.includes(`${rowIndex}_${colIndex}`)" v-show="!hideCells.includes(`${rowIndex}_${colIndex}`)"
@mousedown="$event => handleCellMousedown($event, rowIndex, colIndex)" @mousedown="$event => handleCellMousedown($event, rowIndex, colIndex)"
@mouseenter="handleCellMouseenter(rowIndex, colIndex)" @mouseenter="handleCellMouseenter(rowIndex, colIndex)"
v-contextmenu="el => contextmenus(el)" v-contextmenu="(el: HTMLElement) => contextmenus(el)"
> >
<CustomTextarea <CustomTextarea
v-if="activedCell === `${rowIndex}_${colIndex}`" v-if="activedCell === `${rowIndex}_${colIndex}`"
class="cell-text" class="cell-text"
:class="{ 'active': activedCell === `${rowIndex}_${colIndex}` }" :class="{ 'active': activedCell === `${rowIndex}_${colIndex}` }"
contenteditable="plaintext-only"
:value="cell.text" :value="cell.text"
@updateValue="value => handleInput(value, rowIndex, colIndex)" @updateValue="value => handleInput(value, rowIndex, colIndex)"
@insertExcelData="value => insertExcelData(value, rowIndex, colIndex)" @insertExcelData="value => insertExcelData(value, rowIndex, colIndex)"

View File

@ -81,7 +81,7 @@ export default defineComponent({
const { addHistorySnapshot } = useHistorySnapshot() const { addHistorySnapshot } = useHistorySnapshot()
const handleSelectElement = (e: MouseEvent) => { const handleSelectElement = (e: MouseEvent | TouchEvent) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -1,10 +1,11 @@
import { CSSProperties } from 'vue'
import { TableCellStyle } from '@/types/slides' import { TableCellStyle } from '@/types/slides'
/** /**
* *
* @param style * @param style
*/ */
export const getTextStyle = (style?: TableCellStyle) => { export const getTextStyle = (style?: TableCellStyle): CSSProperties => {
if (!style) return {} if (!style) return {}
const { const {
bold, bold,

View File

@ -30,10 +30,7 @@
/> />
<div <div
class="text ProseMirror-static" class="text ProseMirror-static"
:style="{ :style="cssVar"
'--textIndent': `${elementInfo.textIndent || 0}px`,
'--paragraphSpace': `${elementInfo.paragraphSpace === undefined ? 5 : elementInfo.paragraphSpace}px`,
}"
v-html="elementInfo.content" v-html="elementInfo.content"
></div> ></div>
</div> </div>
@ -42,7 +39,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType, computed } from 'vue' import { defineComponent, PropType, computed, StyleValue } from 'vue'
import { PPTTextElement } from '@/types/slides' import { PPTTextElement } from '@/types/slides'
import ElementOutline from '@/views/components/element/ElementOutline.vue' import ElementOutline from '@/views/components/element/ElementOutline.vue'
@ -63,8 +60,14 @@ export default defineComponent({
const shadow = computed(() => props.elementInfo.shadow) const shadow = computed(() => props.elementInfo.shadow)
const { shadowStyle } = useElementShadow(shadow) const { shadowStyle } = useElementShadow(shadow)
const cssVar = computed(() => ({
'--textIndent': `${props.elementInfo.textIndent || 0}px`,
'--paragraphSpace': `${props.elementInfo.paragraphSpace === undefined ? 5 : props.elementInfo.paragraphSpace}px`,
} as StyleValue))
return { return {
shadowStyle, shadowStyle,
cssVar,
} }
}, },
}) })

View File

@ -101,7 +101,7 @@ export default defineComponent({
const shadow = computed(() => props.elementInfo.shadow) const shadow = computed(() => props.elementInfo.shadow)
const { shadowStyle } = useElementShadow(shadow) const { shadowStyle } = useElementShadow(shadow)
const handleSelectElement = (e: MouseEvent, canMove = true) => { const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()

View File

@ -53,8 +53,8 @@
</div> </div>
<div <div
class="volume-bar-wrap" class="volume-bar-wrap"
@mousedown="$event => handleMousedownVolumeBar($event)" @mousedown="handleMousedownVolumeBar()"
@touchstart="$event => handleMousedownVolumeBar($event)" @touchstart="handleMousedownVolumeBar()"
@click="$event => handleClickVolumeBar($event)" @click="$event => handleClickVolumeBar($event)"
> >
<div class="volume-bar" ref="volumeBarRef"> <div class="volume-bar" ref="volumeBarRef">
@ -94,8 +94,8 @@
<div <div
class="bar-wrap" class="bar-wrap"
ref="playBarWrap" ref="playBarWrap"
@mousedown="$event => handleMousedownPlayBar($event)" @mousedown="handleMousedownPlayBar()"
@touchstart="$event => handleMousedownPlayBar($event)" @touchstart="handleMousedownPlayBar()"
@mousemove="$event => handleMousemovePlayBar($event)" @mousemove="$event => handleMousemovePlayBar($event)"
@mouseenter="playBarTimeVisible = true" @mouseenter="playBarTimeVisible = true"
@mouseleave="playBarTimeVisible = false" @mouseleave="playBarTimeVisible = false"

View File

@ -67,7 +67,7 @@ export default defineComponent({
setup(props) { setup(props) {
const { canvasScale } = storeToRefs(useMainStore()) const { canvasScale } = storeToRefs(useMainStore())
const handleSelectElement = (e: MouseEvent, canMove = true) => { const handleSelectElement = (e: MouseEvent | TouchEvent, canMove = true) => {
if (props.elementInfo.lock) return if (props.elementInfo.lock) return
e.stopPropagation() e.stopPropagation()