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-debugger': isProduction ? 'error' : 'warn',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/ban-types': ['error', {
'extendDefaults': true,
'types': {
'{}': false,
},
}],
},
overrides: [
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,24 +2,24 @@
<div class="multi-position-panel">
<ButtonGroup class="row">
<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 :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 :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>
</ButtonGroup>
<ButtonGroup class="row">
<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 :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 :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>
</ButtonGroup>
<ButtonGroup class="row" v-if="displayItemCount > 2">
@ -68,6 +68,7 @@ export default defineComponent({
uniformHorizontalDisplay,
uniformVerticalDisplay,
alignElement,
ElementAlignCommands,
}
},
})

View File

@ -5,7 +5,7 @@
<Select
style="flex: 10;"
:value="background.type"
@change="value => updateBackgroundType(value)"
@change="value => updateBackgroundType(value as 'gradient' | 'image' | 'solid')"
>
<SelectOption value="solid">纯色填充</SelectOption>
<SelectOption value="image">图片填充</SelectOption>
@ -26,7 +26,7 @@
<Select
style="flex: 10;"
:value="background.imageSize || 'cover'"
@change="value => updateBackground({ imageSize: value })"
@change="value => updateBackground({ imageSize: value as 'repeat' | 'cover' | 'contain' })"
v-else-if="background.type === 'image'"
>
<SelectOption value="contain">缩放</SelectOption>
@ -37,7 +37,7 @@
<Select
style="flex: 10;"
:value="background.gradientType"
@change="value => updateBackground({ gradientType: value })"
@change="value => updateBackground({ gradientType: value as 'linear' | 'radial' })"
v-else
>
<SelectOption value="linear">线性渐变</SelectOption>
@ -61,11 +61,11 @@
<Popover trigger="click">
<template #content>
<ColorPicker
:modelValue="background.gradientColor[0]"
@update:modelValue="value => updateBackground({ gradientColor: [value, background.gradientColor[1]] })"
:modelValue="background.gradientColor![0]"
@update:modelValue="value => updateBackground({ gradientColor: [value, background.gradientColor![1]] })"
/>
</template>
<ColorButton :color="background.gradientColor[0]" style="flex: 3;" />
<ColorButton :color="background.gradientColor![0]" style="flex: 3;" />
</Popover>
</div>
<div class="row">
@ -73,11 +73,11 @@
<Popover trigger="click">
<template #content>
<ColorPicker
:modelValue="background.gradientColor[1]"
@update:modelValue="value => updateBackground({ gradientColor: [background.gradientColor[0], value] })"
:modelValue="background.gradientColor![1]"
@update:modelValue="value => updateBackground({ gradientColor: [background.gradientColor![0], value] })"
/>
</template>
<ColorButton :color="background.gradientColor[1]" style="flex: 3;" />
<ColorButton :color="background.gradientColor![1]" style="flex: 3;" />
</Popover>
</div>
<div class="row" v-if="background.gradientType === 'linear'">
@ -88,7 +88,7 @@
:max="360"
:step="15"
:value="background.gradientRotate"
@change="value => updateBackground({ gradientRotate: value })"
@change="value => updateBackground({ gradientRotate: value as number })"
/>
</div>
</div>
@ -99,7 +99,7 @@
<div class="row">
<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.625">宽屏 16 10</SelectOption>
<SelectOption :value="0.75">标准 4 3</SelectOption>
@ -114,7 +114,7 @@
<Select
style="flex: 3;"
:value="theme.fontName"
@change="value => updateTheme({ fontName: value })"
@change="value => updateTheme({ fontName: value as string })"
>
<SelectOptGroup label="系统字体">
<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;">
<Switch
:checked="hasFilters"
@change="checked => toggleFilters(checked)"
@change="checked => toggleFilters(checked as boolean)"
/>
</div>
</div>
@ -18,7 +18,7 @@
:min="0"
:step="filter.step"
:value="filter.value"
@change="value => updateFilter(filter, value)"
@change="value => updateFilter(filter, value as number)"
/>
</div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

@ -40,7 +40,7 @@ export default defineComponent({
required: true,
},
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,
},
},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,7 +35,7 @@
>
<div
:class="['clip-point', point, rotateClassName]"
v-for="point in ['left-top', 'right-top', 'left-bottom', 'right-bottom']"
v-for="point in cornerPoint"
:key="point"
@mousedown.stop="$event => scaleClipRange($event, point)"
>
@ -49,7 +49,7 @@
</div>
<div
:class="['clip-point', point, rotateClassName]"
v-for="point in ['top', 'bottom', 'left', 'right']"
v-for="point in edgePoints"
:key="point"
@mousedown.stop="$event => scaleClipRange($event, point)"
>
@ -70,7 +70,8 @@ import { computed, defineComponent, onMounted, onUnmounted, PropType, ref } from
import { storeToRefs } from 'pinia'
import { useMainStore, useKeyboardStore } from '@/store'
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({
name: 'image-clip-handler',
@ -81,7 +82,7 @@ export default defineComponent({
required: true,
},
clipData: {
type: Object as PropType<ImageClipData>,
type: Object as PropType<ImageElementClip>,
},
clipPath: {
type: String,
@ -527,12 +528,27 @@ export default defineComponent({
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 {
clipWrapperPositionStyle,
bottomImgPositionStyle,
topImgWrapperPositionStyle,
topImgPositionStyle,
rotateClassName,
edgePoints,
cornerPoint,
handleClip,
moveClipRange,
scaleClipRange,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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