refactor: 替换Tabs、Modal、Message、TextArea、Drawer

This commit is contained in:
pipipi-pikachu 2023-09-24 16:17:07 +08:00
parent a869633a30
commit 9206ef8596
33 changed files with 218 additions and 413 deletions

View File

@ -47,6 +47,7 @@ const handleClick = () => {
color: $textColor; color: $textColor;
border-radius: $borderRadius; border-radius: $borderRadius;
user-select: none; user-select: none;
letter-spacing: 2px;
cursor: pointer; cursor: pointer;
&.default { &.default {

View File

@ -80,6 +80,7 @@ import { computed, onMounted, ref, watch } from 'vue'
import tinycolor, { type ColorFormats } from 'tinycolor2' import tinycolor, { type ColorFormats } from 'tinycolor2'
import { debounce } from 'lodash' import { debounce } from 'lodash'
import { toCanvas } from 'html-to-image' import { toCanvas } from 'html-to-image'
import message from '@/utils/message'
import Alpha from './Alpha.vue' import Alpha from './Alpha.vue'
import Checkboard from './Checkboard.vue' import Checkboard from './Checkboard.vue'
@ -87,8 +88,6 @@ import Hue from './Hue.vue'
import Saturation from './Saturation.vue' import Saturation from './Saturation.vue'
import EditableInput from './EditableInput.vue' import EditableInput from './EditableInput.vue'
import { message } from 'ant-design-vue'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
modelValue?: string modelValue?: string
}>(), { }>(), {

View File

@ -1,12 +1,15 @@
<template> <template>
<Teleport to="body"> <Teleport to="body">
<Transition :name="`drawer-slide-${placement}`"> <Transition :name="`drawer-slide-${placement}`"
@afterLeave="contentVisible = false"
@before-enter="contentVisible = true"
>
<div :class="['drawer', placement]" v-show="visible" :style="{ width: props.width + 'px' }"> <div :class="['drawer', placement]" v-show="visible" :style="{ width: props.width + 'px' }">
<div class="header"> <div class="header">
<slot name="title"></slot> <slot name="title"></slot>
<span class="close-btn" @click="emit('update:visible', false)"><IconClose /></span> <span class="close-btn" @click="emit('update:visible', false)"><IconClose /></span>
</div> </div>
<div class="content" v-if="visible" :style="contentStyle"> <div class="content" v-if="contentVisible" :style="contentStyle">
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
@ -15,7 +18,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, type CSSProperties } from 'vue' import { computed, ref, type CSSProperties } from 'vue'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
visible: boolean visible: boolean
@ -31,6 +34,8 @@ const emit = defineEmits<{
(event: 'update:visible', payload: boolean): void (event: 'update:visible', payload: boolean): void
}>() }>()
const contentVisible = ref(false)
const contentStyle = computed(() => { const contentStyle = computed(() => {
return { return {
width: props.width + 'px', width: props.width + 'px',

View File

@ -17,26 +17,19 @@
</div> </div>
</div> </div>
<div class="right"> <div class="right">
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" v-model:value="toolbarState"
:class="{ 'active': tab.value === toolbarState }" card
v-for="tab in tabs" />
:key="tab.value"
@click="toolbarState = tab.value"
>{{tab.label}}</div>
</div>
<div class="content"> <div class="content">
<div class="symbol" v-if="toolbarState === 'symbol'"> <div class="symbol" v-if="toolbarState === 'symbol'">
<div class="symbol-tabs"> <Tabs
<div :tabs="symbolTabs"
class="symbol-tab" v-model:value="selectedSymbolKey"
:class="{ 'active': selectedSymbolKey === group.type }" spaceBetween
v-for="group in symbolList" :tabsStyle="{ margin: '10px 10px 0' }"
:key="group.type" />
@click="selectedSymbolKey = group.type"
>{{group.label}}</div>
</div>
<div class="symbol-pool"> <div class="symbol-pool">
<div class="symbol-item" v-for="item in symbolPool" :key="item.latex" @click="insertSymbol(item.latex)"> <div class="symbol-item" v-for="item in symbolPool" :key="item.latex" @click="insertSymbol(item.latex)">
<SymbolContent :latex="item.latex" /> <SymbolContent :latex="item.latex" />
@ -69,25 +62,22 @@
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import { hfmath } from './hfmath' import { hfmath } from './hfmath'
import { FORMULA_LIST, SYMBOL_LIST } from '@/configs/latex' import { FORMULA_LIST, SYMBOL_LIST } from '@/configs/latex'
import message from '@/utils/message'
import FormulaContent from './FormulaContent.vue' import FormulaContent from './FormulaContent.vue'
import SymbolContent from './SymbolContent.vue' import SymbolContent from './SymbolContent.vue'
import Button from '../Button.vue'
import TextArea from '../TextArea.vue'
import Tabs from '../Tabs.vue'
import { interface TabItem {
Button, key: 'symbol' | 'formula'
Input,
message,
} from 'ant-design-vue'
const TextArea = Input.TextArea
interface Tab {
label: string label: string
value: 'symbol' | 'formula'
} }
const tabs: Tab[] = [ const tabs: TabItem[] = [
{ label: '常用符号', value: 'symbol' }, { label: '常用符号', key: 'symbol' },
{ label: '预置公式', value: 'formula' }, { label: '预置公式', key: 'formula' },
] ]
interface LatexResult { interface LatexResult {
@ -109,7 +99,11 @@ const emit = defineEmits<{
}>() }>()
const formulaList = FORMULA_LIST const formulaList = FORMULA_LIST
const symbolList = SYMBOL_LIST
const symbolTabs = SYMBOL_LIST.map(item => ({
label: item.label,
key: item.type,
}))
const latex = ref('') const latex = ref('')
const toolbarState = ref<'symbol' | 'formula'>('symbol') const toolbarState = ref<'symbol' | 'formula'>('symbol')
@ -160,6 +154,7 @@ const insertSymbol = (latex: string) => {
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-shrink: 0;
} }
.input-area { .input-area {
flex: 1; flex: 1;
@ -186,6 +181,7 @@ const insertSymbol = (latex: string) => {
} }
.placeholder { .placeholder {
color: #888; color: #888;
font-size: 13px;
} }
.preview-content { .preview-content {
width: 100%; width: 100%;
@ -196,40 +192,15 @@ const insertSymbol = (latex: string) => {
align-items: center; align-items: center;
} }
.right { .right {
width: 280px;
height: 100%; height: 100%;
margin-left: 20px; margin-left: 20px;
flex: 1;
border: solid 1px $borderColor; border: solid 1px $borderColor;
background-color: #fff; background-color: #fff;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
user-select: none; user-select: none;
} }
.tabs {
height: 40px;
font-size: 12px;
flex-shrink: 0;
display: flex;
user-select: none;
}
.tab {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
background-color: $lightGray;
border-bottom: 1px solid $borderColor;
cursor: pointer;
&.active {
background-color: #fff;
border-bottom-color: #fff;
}
& + .tab {
border-left: 1px solid $borderColor;
}
}
.content { .content {
height: calc(100% - 40px); height: calc(100% - 40px);
font-size: 13px; font-size: 13px;
@ -258,22 +229,6 @@ const insertSymbol = (latex: string) => {
cursor: pointer; cursor: pointer;
} }
} }
.symbol-tabs {
display: flex;
justify-content: space-around;
align-items: center;
border-bottom: 1px solid $borderColor;
margin: 12px 12px 5px;
}
.symbol-tab {
padding: 6px 10px;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
}
.symbol { .symbol {
height: 100%; height: 100%;
display: flex; display: flex;

View File

@ -21,11 +21,10 @@
<div class="title" v-if="title">{{ title }}</div> <div class="title" v-if="title">{{ title }}</div>
<div class="description">{{ message }}</div> <div class="description">{{ message }}</div>
</div> </div>
<div class="control"> <div class="control" v-if="closable">
<span <span
class="close-btn" class="close-btn"
@click="close()" @click="close()"
v-if="closable"
> >
<IconCloseSmall /> <IconCloseSmall />
</span> </span>
@ -100,7 +99,7 @@ defineExpose({
} }
} }
.message-container { .message-container {
min-width: 150px; min-width: 50px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 10px; padding: 10px;

View File

@ -3,10 +3,13 @@
<Transition name="modal-fade"> <Transition name="modal-fade">
<div class="modal" ref="modalRef" v-show="visible" tabindex="-1" @keyup.esc="onEsc()"> <div class="modal" ref="modalRef" v-show="visible" tabindex="-1" @keyup.esc="onEsc()">
<div class="mask" @click="onClickMask()"></div> <div class="mask" @click="onClickMask()"></div>
<Transition name="modal-zoom"> <Transition name="modal-zoom"
@afterLeave="contentVisible = false"
@before-enter="contentVisible = true"
>
<div class="modal-content" v-show="visible" :style="contentStyle"> <div class="modal-content" v-show="visible" :style="contentStyle">
<span class="close-btn" v-if="closeButton" @click="emit('update:visible', false)"><IconClose /></span> <span class="close-btn" v-if="closeButton" @click="close()"><IconClose /></span>
<slot v-if="visible"></slot> <slot v-if="contentVisible"></slot>
</div> </div>
</Transition> </Transition>
</div> </div>
@ -38,8 +41,11 @@ const modalRef = ref<HTMLDivElement>()
const emit = defineEmits<{ const emit = defineEmits<{
(event: 'update:visible', payload: boolean): void (event: 'update:visible', payload: boolean): void
(event: 'closed'): void
}>() }>()
const contentVisible = ref(false)
const contentStyle = computed(() => { const contentStyle = computed(() => {
return { return {
width: props.width + 'px', width: props.width + 'px',
@ -53,12 +59,17 @@ watch(() => props.visible, () => {
} }
}) })
const close = () => {
emit('update:visible', false)
emit('closed')
}
const onEsc = () => { const onEsc = () => {
if (props.visible && props.closeOnEsc) emit('update:visible', false) if (props.visible && props.closeOnEsc) close()
} }
const onClickMask = () => { const onClickMask = () => {
if (props.closeOnClickMask) emit('update:visible', false) if (props.closeOnClickMask) close()
} }
</script> </script>
@ -87,7 +98,7 @@ const onClickMask = () => {
.modal-content { .modal-content {
z-index: 5001; z-index: 5001;
padding: 15px; padding: 20px;
background: #fff; background: #fff;
border-radius: $borderRadius; border-radius: $borderRadius;
box-shadow: 0 1px 3px rgba(0, 0, 0, .2); box-shadow: 0 1px 3px rgba(0, 0, 0, .2);
@ -101,8 +112,8 @@ const onClickMask = () => {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: absolute; position: absolute;
top: 10px; top: 16px;
right: 12px; right: 16px;
cursor: pointer; cursor: pointer;
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="popover" ref="triggerRef"> <div class="popover" ref="triggerRef">
<div class="popover-content" :style="contentStyle" ref="contentRef"> <div class="popover-content" :style="contentStyle" ref="contentRef">
<slot name="content"></slot> <slot name="content" v-if="contentVisible"></slot>
</div> </div>
<slot></slot> <slot></slot>
</div> </div>
@ -31,6 +31,7 @@ const emit = defineEmits<{
const instance = ref<Instance>() const instance = ref<Instance>()
const triggerRef = ref<HTMLElement>() const triggerRef = ref<HTMLElement>()
const contentRef = ref<HTMLElement>() const contentRef = ref<HTMLElement>()
const contentVisible = ref(false)
const contentStyle = computed(() => { const contentStyle = computed(() => {
return props.contentStyle || {} return props.contentStyle || {}
@ -54,11 +55,15 @@ onMounted(() => {
offset: [0, 8], offset: [0, 8],
duration: 200, duration: 200,
animation: 'scale', animation: 'scale',
onShow() {
contentVisible.value = true
},
onShown() { onShown() {
if (!props.value) emit('update:value', true) if (!props.value) emit('update:value', true)
}, },
onHidden() { onHidden() {
if (props.value) emit('update:value', false) if (props.value) emit('update:value', false)
contentVisible.value = false
}, },
}) })
}) })

View File

@ -1,11 +1,21 @@
<template> <template>
<div class="tabs" :class="{ 'card': card }" :style="tabsStyle || {}"> <div class="tabs"
:class="{
'card': card,
'space-around': spaceAround,
'space-between': spaceBetween,
}"
:style="tabsStyle || {}"
>
<div <div
class="tab" class="tab"
:class="{ 'active': tab.key === value }" :class="{ 'active': tab.key === value }"
v-for="tab in tabs" v-for="tab in tabs"
:key="tab.key" :key="tab.key"
:style="tabStyle || {}" :style="{
...(tabStyle || {}),
'--color': tab.color,
}"
@click="emit('update:value', tab.key)" @click="emit('update:value', tab.key)"
>{{tab.label}}</div> >{{tab.label}}</div>
</div> </div>
@ -17,6 +27,7 @@ import { type CSSProperties } from 'vue'
interface TabItem { interface TabItem {
key: string key: string
label: string label: string
color?: string
} }
withDefaults(defineProps<{ withDefaults(defineProps<{
@ -25,8 +36,12 @@ withDefaults(defineProps<{
card?: boolean card?: boolean
tabsStyle?: CSSProperties tabsStyle?: CSSProperties
tabStyle?: CSSProperties tabStyle?: CSSProperties
spaceAround?: boolean
spaceBetween?: boolean
}>(), { }>(), {
card: false, card: false,
spaceAround: false,
spaceBetween: false,
}) })
const emit = defineEmits<{ const emit = defineEmits<{
@ -36,28 +51,40 @@ const emit = defineEmits<{
<style lang="scss" scoped> <style lang="scss" scoped>
.tabs { .tabs {
font-size: 13px;
display: flex; display: flex;
user-select: none; user-select: none;
line-height: 1;
&:not(.card) { &:not(.card) {
font-size: 13px;
align-items: center; align-items: center;
justify-content: flex-start; justify-content: flex-start;
border-bottom: 1px solid $borderColor; border-bottom: 1px solid $borderColor;
&.space-around {
justify-content: space-around;
}
&.space-between {
justify-content: space-between;
}
.tab { .tab {
padding: 8px 10px;
text-align: center; text-align: center;
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
padding: 8px 10px;
cursor: pointer; cursor: pointer;
&.active { &.active {
border-bottom: 2px solid $themeColor; border-bottom: 2px solid var(--color, $themeColor);
} }
} }
} }
&.card { &.card {
height: 40px;
font-size: 12px;
flex-shrink: 0;
.tab { .tab {
flex: 1; flex: 1;
display: flex; display: flex;

View File

@ -45,6 +45,8 @@ const handleInput = (e: Event) => {
border-radius: $borderRadius; border-radius: $borderRadius;
padding: 10px; padding: 10px;
transition: border-color .25s; transition: border-color .25s;
box-sizing: border-box;
line-height: 1.675;
resize: none; resize: none;
font-family: -apple-system,BlinkMacSystemFont, 'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji'; font-family: -apple-system,BlinkMacSystemFont, 'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji';

View File

@ -2,7 +2,7 @@ import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store' import { useMainStore } from '@/store'
import { copyText, readClipboard } from '@/utils/clipboard' import { copyText, readClipboard } from '@/utils/clipboard'
import { encrypt } from '@/utils/crypto' import { encrypt } from '@/utils/crypto'
import { message } from 'ant-design-vue' import message from '@/utils/message'
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData' import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
import useDeleteElement from './useDeleteElement' import useDeleteElement from './useDeleteElement'

View File

@ -12,7 +12,7 @@ import { type AST, toAST } from '@/utils/htmlParser'
import { type SvgPoints, toPoints } from '@/utils/svgPathParser' import { type SvgPoints, toPoints } from '@/utils/svgPathParser'
import { encrypt } from '@/utils/crypto' import { encrypt } from '@/utils/crypto'
import { svg2Base64 } from '@/utils/svg2Base64' import { svg2Base64 } from '@/utils/svg2Base64'
import { message } from 'ant-design-vue' import message from '@/utils/message'
const INCH_PX_RATIO = 100 const INCH_PX_RATIO = 100
const PT_PX_RATIO = 0.75 const PT_PX_RATIO = 0.75

View File

@ -8,8 +8,7 @@ import { decrypt } from '@/utils/crypto'
import { type ShapePoolItem, SHAPE_LIST, SHAPE_PATH_FORMULAS } from '@/configs/shapes' import { type ShapePoolItem, SHAPE_LIST, SHAPE_PATH_FORMULAS } from '@/configs/shapes'
import { VIEWPORT_SIZE } from '@/configs/canvas' import { VIEWPORT_SIZE } from '@/configs/canvas'
import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements' import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
import message from '@/utils/message'
import { message } from 'ant-design-vue'
export default () => { export default () => {
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()

View File

@ -1,7 +1,7 @@
import { useSlidesStore } from '@/store' import { useSlidesStore } from '@/store'
import type { PPTElement, PPTElementLink } from '@/types/slides' import type { PPTElement, PPTElementLink } from '@/types/slides'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import { message } from 'ant-design-vue' import message from '@/utils/message'
export default () => { export default () => {
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()

View File

@ -2,7 +2,7 @@ import { nextTick, onBeforeUnmount, ref, watch } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import type { PPTTableElement } from '@/types/slides' import type { PPTTableElement } from '@/types/slides'
import { message } from 'ant-design-vue' import message from '@/utils/message'
interface SearchTextResult { interface SearchTextResult {
elType: 'text' | 'shape' elType: 'text' | 'shape'

View File

@ -7,7 +7,7 @@ import { copyText, readClipboard } from '@/utils/clipboard'
import { encrypt } from '@/utils/crypto' import { encrypt } from '@/utils/crypto'
import { createElementIdMap } from '@/utils/element' import { createElementIdMap } from '@/utils/element'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import { message } from 'ant-design-vue' import message from '@/utils/message'
import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData' import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import useAddSlidesOrElements from '@/hooks//useAddSlidesOrElements' import useAddSlidesOrElements from '@/hooks//useAddSlidesOrElements'

View File

@ -1,14 +1,10 @@
<template> <template>
<div class="link-dialog"> <div class="link-dialog">
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" v-model:value="type"
:class="{ 'active': type === tab.key }" :tabsStyle="{ marginBottom: '20px' }"
v-for="tab in tabs" />
:key="tab.key"
@click="type = tab.key"
>{{tab.label}}</div>
</div>
<Input <Input
class="input" class="input"
@ -32,7 +28,7 @@
<div class="preview" v-if="type === 'slide' && selectedSlide"> <div class="preview" v-if="type === 'slide' && selectedSlide">
<div>预览</div> <div>预览</div>
<ThumbnailSlide class="thumbnail" :slide="selectedSlide" :size="490" /> <ThumbnailSlide class="thumbnail" :slide="selectedSlide" :size="500" />
</div> </div>
<div class="btns"> <div class="btns">
@ -50,6 +46,7 @@ import type { PPTElementLink } from '@/types/slides'
import useLink from '@/hooks/useLink' import useLink from '@/hooks/useLink'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue' import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
import Tabs from '@/components/Tabs.vue'
import { import {
Button, Button,
Select, Select,
@ -112,21 +109,9 @@ const save = () => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.tabs { .link-dialog {
display: flex; font-size: 13px;
justify-content: flex-start; line-height: 1.675;
align-items: center;
border-bottom: 1px solid $borderColor;
margin-bottom: 20px;
}
.tab {
padding: 0 10px 8px;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
} }
.input { .input {
width: 100%; width: 100%;
@ -136,7 +121,7 @@ const save = () => {
margin-top: 12px; margin-top: 12px;
} }
.thumbnail { .thumbnail {
outline: 1px solid rgba($color: $themeColor, $alpha: .15); border: 1px solid rgba($color: $themeColor, $alpha: .15);
margin-top: 5px; margin-top: 5px;
} }
.btns { .btns {

View File

@ -23,8 +23,7 @@ import { storeToRefs } from 'pinia'
import { useKeyboardStore, useMainStore } from '@/store' import { useKeyboardStore, useMainStore } from '@/store'
import type { CreateCustomShapeData } from '@/types/edit' import type { CreateCustomShapeData } from '@/types/edit'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import message from '@/utils/message'
import { message } from 'ant-design-vue'
const emit = defineEmits<{ const emit = defineEmits<{
(event: 'created', payload: CreateCustomShapeData): void (event: 'created', payload: CreateCustomShapeData): void

View File

@ -88,12 +88,8 @@
<Ruler :viewportStyles="viewportStyles" v-if="showRuler" /> <Ruler :viewportStyles="viewportStyles" v-if="showRuler" />
<Modal <Modal
v-model:open="linkDialogVisible" v-model:visible="linkDialogVisible"
:footer="null"
centered
:closable="false"
:width="540" :width="540"
destroyOnClose
> >
<LinkDialog @close="linkDialogVisible = false" /> <LinkDialog @close="linkDialogVisible = false" />
</Modal> </Modal>
@ -141,7 +137,7 @@ import ShapeCreateCanvas from './ShapeCreateCanvas.vue'
import MultiSelectOperate from './Operate/MultiSelectOperate.vue' import MultiSelectOperate from './Operate/MultiSelectOperate.vue'
import Operate from './Operate/index.vue' import Operate from './Operate/index.vue'
import LinkDialog from './LinkDialog.vue' import LinkDialog from './LinkDialog.vue'
import { Modal } from 'ant-design-vue' import Modal from '@/components/Modal.vue'
const mainStore = useMainStore() const mainStore = useMainStore()
const { const {

View File

@ -1,14 +1,10 @@
<template> <template>
<div class="media-input"> <div class="media-input">
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" v-model:value="type"
:class="{ 'active': type === tab.key }" :tabsStyle="{ marginBottom: '15px' }"
v-for="tab in tabs" />
:key="tab.key"
@click="type = tab.key"
>{{tab.label}}</div>
</div>
<template v-if="type === 'video'"> <template v-if="type === 'video'">
<Input v-model:value="videoSrc" placeholder="请输入视频地址e.g. https://xxx.mp4"></Input> <Input v-model:value="videoSrc" placeholder="请输入视频地址e.g. https://xxx.mp4"></Input>
@ -35,6 +31,7 @@ import {
Input, Input,
message, message,
} from 'ant-design-vue' } from 'ant-design-vue'
import Tabs from '@/components/Tabs.vue'
type TypeKey = 'video' | 'audio' type TypeKey = 'video' | 'audio'
interface TabItem { interface TabItem {
@ -73,22 +70,6 @@ const insertAudio = () => {
.media-input { .media-input {
width: 480px; width: 480px;
} }
.tabs {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid $borderColor;
margin-bottom: 20px;
}
.tab {
padding: 0 10px 8px;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
}
.btns { .btns {
margin-top: 10px; margin-top: 10px;
text-align: right; text-align: right;

View File

@ -109,12 +109,8 @@
</div> </div>
<Modal <Modal
v-model:open="latexEditorVisible" v-model:visible="latexEditorVisible"
:footer="null"
centered
:closable="false"
:width="880" :width="880"
destroyOnClose
> >
<LaTeXEditor <LaTeXEditor
@close="latexEditorVisible = false" @close="latexEditorVisible = false"
@ -142,11 +138,11 @@ import TableGenerator from './TableGenerator.vue'
import MediaInput from './MediaInput.vue' import MediaInput from './MediaInput.vue'
import LaTeXEditor from '@/components/LaTeXEditor/index.vue' import LaTeXEditor from '@/components/LaTeXEditor/index.vue'
import FileInput from '@/components/FileInput.vue' import FileInput from '@/components/FileInput.vue'
import Modal from '@/components/Modal.vue'
import { import {
Tooltip, Tooltip,
Popover, Popover,
Divider, Divider,
Modal,
} from 'ant-design-vue' } from 'ant-design-vue'
const mainStore = useMainStore() const mainStore = useMainStore()

View File

@ -19,14 +19,14 @@ import { HOTKEY_DOC } from '@/configs/hotkey'
height: 100%; height: 100%;
overflow: auto; overflow: auto;
font-size: 12px; font-size: 12px;
margin: 0 -24px; margin: 0 -15px;
padding: 0 24px; padding: 0 15px 15px;
} }
.title { .title {
font-size: 14px; font-size: 14px;
font-weight: 700; font-weight: 700;
border-bottom: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5;
padding: 24px 0 5px 0; padding: 25px 0 5px 0;
&:first-child { &:first-child {
padding-top: 0; padding-top: 0;

View File

@ -65,11 +65,9 @@
</div> </div>
<Drawer <Drawer
width="320" :width="320"
v-model:visible="hotkeyDrawerVisible"
placement="right" placement="right"
:closable="false"
:open="hotkeyDrawerVisible"
@close="hotkeyDrawerVisible = false"
> >
<HotkeyDoc /> <HotkeyDoc />
</Drawer> </Drawer>
@ -90,9 +88,9 @@ import type { DialogForExportTypes } from '@/types/export'
import HotkeyDoc from './HotkeyDoc.vue' import HotkeyDoc from './HotkeyDoc.vue'
import FileInput from '@/components/FileInput.vue' import FileInput from '@/components/FileInput.vue'
import FullscreenSpin from '@/components/FullscreenSpin.vue' import FullscreenSpin from '@/components/FullscreenSpin.vue'
import Drawer from '@/components/Drawer.vue'
import { import {
Tooltip, Tooltip,
Drawer,
Popover, Popover,
Input, Input,
} from 'ant-design-vue' } from 'ant-design-vue'

View File

@ -1,14 +1,11 @@
<template> <template>
<div class="export-dialog"> <div class="export-dialog">
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" :value="dialogForExport"
:class="{ 'active': tab.key === dialogForExport }" card
v-for="tab in tabs" @update:value="key => setDialogForExport(key as DialogForExportTypes)"
:key="tab.key" />
@click="setDialogForExport(tab.key)"
>{{tab.label}}</div>
</div>
<div class="content"> <div class="content">
<component :is="currentDialogComponent" @close="setDialogForExport('')"></component> <component :is="currentDialogComponent" @close="setDialogForExport('')"></component>
</div> </div>
@ -26,6 +23,7 @@ import ExportJSON from './ExportJSON.vue'
import ExportPDF from './ExportPDF.vue' import ExportPDF from './ExportPDF.vue'
import ExportPPTX from './ExportPPTX.vue' import ExportPPTX from './ExportPPTX.vue'
import ExportSpecificFile from './ExportSpecificFile.vue' import ExportSpecificFile from './ExportSpecificFile.vue'
import Tabs from '@/components/Tabs.vue'
interface TabItem { interface TabItem {
key: DialogForExportTypes key: DialogForExportTypes
@ -60,35 +58,7 @@ const currentDialogComponent = computed<unknown>(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.export-dialog { .export-dialog {
margin: -20px -24px; margin: -20px;
}
.tabs {
height: 50px;
font-size: 12px;
flex-shrink: 0;
display: flex;
user-select: none;
border-top-left-radius: $borderRadius;
border-top-right-radius: $borderRadius;
overflow: hidden;
}
.tab {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
background-color: $lightGray;
border-bottom: 1px solid $borderColor;
cursor: pointer;
&.active {
background-color: #fff;
border-bottom-color: #fff;
}
& + .tab {
border-left: 1px solid $borderColor;
}
} }
.content { .content {
height: 460px; height: 460px;

View File

@ -7,16 +7,10 @@
:top="90" :top="90"
> >
<div class="close-btn" @click="close()" @mousedown.stop><IconClose /></div> <div class="close-btn" @click="close()" @mousedown.stop><IconClose /></div>
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" v-model:value="type"
:class="{ 'active': type === tab.key }" />
v-for="tab in tabs"
:key="tab.key"
@click="changeTab(tab.key)"
@mousedown.stop
>{{tab.label}}</div>
</div>
<div class="content" :class="type" @mousedown.stop> <div class="content" :class="type" @mousedown.stop>
<Input class="input" v-model:value="searchWord" placeholder="输入查找内容" @keydown.enter="searchNext()" ref="searchInpRef"> <Input class="input" v-model:value="searchWord" placeholder="输入查找内容" @keydown.enter="searchNext()" ref="searchInpRef">
@ -37,10 +31,11 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, onMounted, ref } from 'vue' import { nextTick, onMounted, ref, watch } from 'vue'
import { useMainStore } from '@/store' import { useMainStore } from '@/store'
import useSearch from '@/hooks/useSearch' import useSearch from '@/hooks/useSearch'
import MoveablePanel from '@/components/MoveablePanel.vue' import MoveablePanel from '@/components/MoveablePanel.vue'
import Tabs from '@/components/Tabs.vue'
import { import {
Button, Button,
Input, Input,
@ -81,35 +76,17 @@ onMounted(() => {
searchInpRef.value!.focus() searchInpRef.value!.focus()
}) })
const changeTab = (key: TypeKey) => { watch(type, () => {
type.value = key
nextTick(() => { nextTick(() => {
searchInpRef.value!.focus() searchInpRef.value!.focus()
}) })
} })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.search-panel { .search-panel {
font-size: 13px; font-size: 13px;
} }
.tabs {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid $borderColor;
line-height: 1.5;
user-select: none;
}
.tab {
padding: 0 10px 8px;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
}
.content { .content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -143,10 +120,10 @@ const changeTab = (key: TypeKey) => {
margin-top: 10px; margin-top: 10px;
} }
.close-btn { .close-btn {
width: 40px; width: 32px;
height: 40px; height: 32px;
position: absolute; position: absolute;
top: 0; top: 8px;
right: 0; right: 0;
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@ -7,14 +7,13 @@
@openChange="visible => handlePopoverVisibleChange(visible)" @openChange="visible => handlePopoverVisibleChange(visible)"
> >
<template #content> <template #content>
<div class="tabs"> <Tabs
<div :tabs="tabs"
:class="['tab', tab.key, { 'active': activeTab === tab.key }]" v-model:value="activeTab"
v-for="tab in tabs" :tabsStyle="{ marginBottom: '20px' }"
:key="tab.key" :tabStyle="{ width: '33.333%' }"
@click="activeTab = tab.key" spaceAround
>{{tab.label}}</div> />
</div>
<template v-for="key in animationTypes"> <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]">
@ -130,7 +129,7 @@ import {
import { ELEMENT_TYPE_ZH } from '@/configs/element' import { ELEMENT_TYPE_ZH } from '@/configs/element'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import Tabs from '@/components/Tabs.vue'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import { import {
InputNumber, InputNumber,
@ -163,6 +162,7 @@ type AnimationType = 'in' | 'out' | 'attention'
interface TabItem { interface TabItem {
key: AnimationType key: AnimationType
label: string label: string
color: string,
} }
const animationTypes: AnimationType[] = ['in', 'out', 'attention'] const animationTypes: AnimationType[] = ['in', 'out', 'attention']
@ -172,9 +172,9 @@ const { handleElement, handleElementId } = storeToRefs(useMainStore())
const { currentSlide, formatedAnimations, currentSlideAnimations } = storeToRefs(slidesStore) const { currentSlide, formatedAnimations, currentSlideAnimations } = storeToRefs(slidesStore)
const tabs: TabItem[] = [ const tabs: TabItem[] = [
{ key: 'in', label: '入场' }, { key: 'in', label: '入场', color: '#68a490' },
{ key: 'out', label: '退场' }, { key: 'out', label: '退场', color: '#d86344' },
{ key: 'attention', label: '强调' }, { key: 'attention', label: '强调', color: '#e8b76a' },
] ]
const activeTab = ref('in') const activeTab = ref('in')
@ -348,33 +348,6 @@ $attentionColor: #e8b76a;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.tabs {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid $borderColor;
margin-bottom: 20px;
}
.tab {
width: 33.33%;
padding-bottom: 8px;
border-bottom: 2px solid transparent;
text-align: center;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
&.in.active {
border-bottom-color: $inColor;
}
&.out.active {
border-bottom-color: $outColor;
}
&.attention.active {
border-bottom-color: $attentionColor;
}
}
.element-animation { .element-animation {
height: 32px; height: 32px;
display: flex; display: flex;

View File

@ -135,12 +135,8 @@
<ElementOutline /> <ElementOutline />
<Modal <Modal
v-model:open="chartDataEditorVisible" v-model:visible="chartDataEditorVisible"
:footer="null" :width="640"
centered
:closable="false"
:width="648"
destroyOnClose
> >
<ChartDataEditor <ChartDataEditor
:data="handleChartElement.data" :data="handleChartElement.data"
@ -163,13 +159,13 @@ import ElementOutline from '../../common/ElementOutline.vue'
import ColorButton from '../../common/ColorButton.vue' import ColorButton from '../../common/ColorButton.vue'
import ChartDataEditor from './ChartDataEditor.vue' import ChartDataEditor from './ChartDataEditor.vue'
import ColorPicker from '@/components/ColorPicker/index.vue' import ColorPicker from '@/components/ColorPicker/index.vue'
import Modal from '@/components/Modal.vue'
import { import {
Divider, Divider,
Button, Button,
Tooltip, Tooltip,
Popover, Popover,
Select, Select,
Modal,
Checkbox, Checkbox,
} from 'ant-design-vue' } from 'ant-design-vue'
const ButtonGroup = Button.Group const ButtonGroup = Button.Group

View File

@ -28,12 +28,8 @@
</div> </div>
<Modal <Modal
v-model:open="latexEditorVisible" v-model:visible="latexEditorVisible"
:footer="null"
centered
:closable="false"
:width="880" :width="880"
destroyOnClose
> >
<LaTeXEditor <LaTeXEditor
:value="handleLatexElement.latex" :value="handleLatexElement.latex"
@ -55,12 +51,12 @@ import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import ColorButton from '../common/ColorButton.vue' import ColorButton from '../common/ColorButton.vue'
import LaTeXEditor from '@/components/LaTeXEditor/index.vue' import LaTeXEditor from '@/components/LaTeXEditor/index.vue'
import ColorPicker from '@/components/ColorPicker/index.vue' import ColorPicker from '@/components/ColorPicker/index.vue'
import Modal from '@/components/Modal.vue'
import { import {
InputNumber, InputNumber,
Divider, Divider,
Button, Button,
Popover, Popover,
Modal,
} from 'ant-design-vue' } from 'ant-design-vue'
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()

View File

@ -1,14 +1,11 @@
<template> <template>
<div class="symbol-panel"> <div class="symbol-panel">
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" v-model:value="selectedSymbolKey"
:class="{ 'active': selectedSymbolKey === item.key }" :tabsStyle="{ marginBottom: '8px' }"
v-for="item in SYMBOL_LIST" spaceBetween
:key="item.key" />
@click="selectedSymbolKey = item.key"
>{{item.label}}</div>
</div>
<div class="pool"> <div class="pool">
<div class="symbol-item" v-for="(item, index) in symbolPool" :key="index" @click="selectSymbol(item)"> <div class="symbol-item" v-for="(item, index) in symbolPool" :key="index" @click="selectSymbol(item)">
<div class="symbol">{{item}}</div> <div class="symbol">{{item}}</div>
@ -21,6 +18,7 @@
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { SYMBOL_LIST } from '@/configs/symbol' import { SYMBOL_LIST } from '@/configs/symbol'
import emitter, { EmitterEvents } from '@/utils/emitter' import emitter, { EmitterEvents } from '@/utils/emitter'
import Tabs from '@/components/Tabs.vue'
const selectedSymbolKey = ref(SYMBOL_LIST[0].key) const selectedSymbolKey = ref(SYMBOL_LIST[0].key)
const symbolPool = computed(() => { const symbolPool = computed(() => {
@ -28,6 +26,11 @@ const symbolPool = computed(() => {
return selectedSymbol?.children || [] return selectedSymbol?.children || []
}) })
const tabs = SYMBOL_LIST.map(item => ({
key: item.key,
label: item.label,
}))
const selectSymbol = (value: string) => { const selectSymbol = (value: string) => {
emitter.emit(EmitterEvents.RICH_TEXT_COMMAND, { action: { command: 'insert', value } }) emitter.emit(EmitterEvents.RICH_TEXT_COMMAND, { action: { command: 'insert', value } })
} }
@ -39,22 +42,6 @@ const selectSymbol = (value: string) => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.tabs {
display: flex;
justify-content: space-around;
align-items: center;
border-bottom: 1px solid $borderColor;
margin-bottom: 8px;
}
.tab {
padding: 6px 10px 8px;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
}
.pool { .pool {
padding: 5px 12px; padding: 5px 12px;
margin: 0 -12px; margin: 0 -12px;

View File

@ -1,14 +1,11 @@
<template> <template>
<div class="toolbar"> <div class="toolbar">
<div class="tabs"> <Tabs
<div :tabs="currentTabs"
class="tab" :value="toolbarState"
:class="{ 'active': tab.value === toolbarState }" card
v-for="tab in currentTabs" @update:value="key => setToolbarState(key as ToolbarStates)"
:key="tab.value" />
@click="setToolbarState(tab.value)"
>{{tab.label}}</div>
</div>
<div class="content"> <div class="content">
<component :is="currentPanelComponent"></component> <component :is="currentPanelComponent"></component>
</div> </div>
@ -28,10 +25,11 @@ import SlideDesignPanel from './SlideDesignPanel.vue'
import SlideAnimationPanel from './SlideAnimationPanel.vue' import SlideAnimationPanel from './SlideAnimationPanel.vue'
import MultiPositionPanel from './MultiPositionPanel.vue' import MultiPositionPanel from './MultiPositionPanel.vue'
import SymbolPanel from './SymbolPanel.vue' import SymbolPanel from './SymbolPanel.vue'
import Tabs from '@/components/Tabs.vue'
interface ElementTabs { interface ElementTabs {
label: string label: string
value: ToolbarStates key: ToolbarStates
} }
const mainStore = useMainStore() const mainStore = useMainStore()
@ -40,26 +38,26 @@ const { activeElementIdList, handleElement, toolbarState } = storeToRefs(mainSto
const elementTabs = computed<ElementTabs[]>(() => { const elementTabs = computed<ElementTabs[]>(() => {
if (handleElement.value?.type === 'text') { if (handleElement.value?.type === 'text') {
return [ return [
{ label: '样式', value: ToolbarStates.EL_STYLE }, { label: '样式', key: ToolbarStates.EL_STYLE },
{ label: '符号', value: ToolbarStates.SYMBOL }, { label: '符号', key: ToolbarStates.SYMBOL },
{ label: '位置', value: ToolbarStates.EL_POSITION }, { label: '位置', key: ToolbarStates.EL_POSITION },
{ label: '动画', value: ToolbarStates.EL_ANIMATION }, { label: '动画', key: ToolbarStates.EL_ANIMATION },
] ]
} }
return [ return [
{ label: '样式', value: ToolbarStates.EL_STYLE }, { label: '样式', key: ToolbarStates.EL_STYLE },
{ label: '位置', value: ToolbarStates.EL_POSITION }, { label: '位置', key: ToolbarStates.EL_POSITION },
{ label: '动画', value: ToolbarStates.EL_ANIMATION }, { label: '动画', key: ToolbarStates.EL_ANIMATION },
] ]
}) })
const slideTabs = [ const slideTabs = [
{ label: '设计', value: ToolbarStates.SLIDE_DESIGN }, { label: '设计', key: ToolbarStates.SLIDE_DESIGN },
{ label: '切换', value: ToolbarStates.SLIDE_ANIMATION }, { label: '切换', key: ToolbarStates.SLIDE_ANIMATION },
{ label: '动画', value: ToolbarStates.EL_ANIMATION }, { label: '动画', key: ToolbarStates.EL_ANIMATION },
] ]
const multiSelectTabs = [ const multiSelectTabs = [
{ label: '样式', value: ToolbarStates.EL_STYLE }, { label: '样式', key: ToolbarStates.EL_STYLE },
{ label: '位置', value: ToolbarStates.MULTI_POSITION }, { label: '位置', key: ToolbarStates.MULTI_POSITION },
] ]
const setToolbarState = (value: ToolbarStates) => { const setToolbarState = (value: ToolbarStates) => {
@ -73,7 +71,7 @@ const currentTabs = computed(() => {
}) })
watch(currentTabs, () => { watch(currentTabs, () => {
const currentTabsValue: ToolbarStates[] = currentTabs.value.map(tab => tab.value) const currentTabsValue: ToolbarStates[] = currentTabs.value.map(tab => tab.key)
if (!currentTabsValue.includes(toolbarState.value)) { if (!currentTabsValue.includes(toolbarState.value)) {
mainStore.setToolbarState(currentTabsValue[0]) mainStore.setToolbarState(currentTabsValue[0])
} }
@ -100,31 +98,6 @@ const currentPanelComponent = computed(() => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.tabs {
height: 40px;
font-size: 12px;
flex-shrink: 0;
display: flex;
user-select: none;
}
.tab {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
background-color: $lightGray;
border-bottom: 1px solid $borderColor;
cursor: pointer;
&.active {
background-color: #fff;
border-bottom-color: #fff;
}
& + .tab {
border-left: 1px solid $borderColor;
}
}
.content { .content {
padding: 12px; padding: 12px;
font-size: 13px; font-size: 13px;

View File

@ -20,13 +20,9 @@
<SearchPanel v-if="showSearchPanel" /> <SearchPanel v-if="showSearchPanel" />
<Modal <Modal
:open="!!dialogForExport" :visible="!!dialogForExport"
:footer="null"
centered
:closable="false"
:width="680" :width="680"
destroyOnClose @closed="closeExportDialog()"
@cancel="closeExportDialog()"
> >
<ExportDialog /> <ExportDialog />
</Modal> </Modal>
@ -48,7 +44,7 @@ import Remark from './Remark/index.vue'
import ExportDialog from './ExportDialog/index.vue' import ExportDialog from './ExportDialog/index.vue'
import SelectPanel from './SelectPanel.vue' import SelectPanel from './SelectPanel.vue'
import SearchPanel from './SearchPanel.vue' import SearchPanel from './SearchPanel.vue'
import { Modal } from 'ant-design-vue' import Modal from '@/components/Modal.vue'
const mainStore = useMainStore() const mainStore = useMainStore()
const { dialogForExport, showSelectPanel, showSearchPanel } = storeToRefs(mainStore) const { dialogForExport, showSelectPanel, showSearchPanel } = storeToRefs(mainStore)

View File

@ -1,14 +1,14 @@
<template> <template>
<div class="element-toolbar"> <div class="element-toolbar">
<div class="tabs"> <Tabs
<div :tabs="tabs"
class="tab" v-model:value="activeTab"
:class="{ 'active': activeTab === item.key }" :tabsStyle="{ marginBottom: '8px' }"
v-for="item in tabs" :tabStyle="{
:key="item.key" width: '30%',
@click="activeTab = item.key" margin: '0 10%',
>{{item.label}}</div> }"
</div> />
<div class="content"> <div class="content">
<div class="style" v-if="activeTab === 'style'"> <div class="style" v-if="activeTab === 'style'">
@ -134,6 +134,7 @@ import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import CheckboxButton from '@/components/CheckboxButton.vue' import CheckboxButton from '@/components/CheckboxButton.vue'
import CheckboxButtonGroup from '@/components/ButtonGroup.vue' import CheckboxButtonGroup from '@/components/ButtonGroup.vue'
import Tabs from '@/components/Tabs.vue'
import { import {
Divider, Divider,
Button, Button,
@ -237,27 +238,6 @@ const updateFill = (color: string) => {
flex-direction: column; flex-direction: column;
animation: slideInUp .15s; animation: slideInUp .15s;
} }
.tabs {
display: flex;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid $borderColor;
font-size: 12px;
font-weight: 700;
margin-bottom: 10px;
}
.tab {
width: 30%;
padding: 10px 10px 12px;
margin: 0 10%;
border-bottom: 2px solid transparent;
text-align: center;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
}
@keyframes slideInUp { @keyframes slideInUp {
from { from {

View File

@ -4,8 +4,7 @@ import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store' import { useSlidesStore } from '@/store'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import { ANIMATION_CLASS_PREFIX } from '@/configs/animation' import { ANIMATION_CLASS_PREFIX } from '@/configs/animation'
import message from '@/utils/message'
import { message } from 'ant-design-vue'
export default () => { export default () => {
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()

View File

@ -74,7 +74,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { message } from 'ant-design-vue' import message from '@/utils/message'
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
src: string src: string