feat: 添加特殊符号输入面板

This commit is contained in:
pipipi-pikachu 2021-08-10 22:35:47 +08:00
parent 71253cecfc
commit e14d37e617
5 changed files with 188 additions and 7 deletions

59
src/configs/symbol.ts Normal file
View File

@ -0,0 +1,59 @@
export const SYMBOL_LIST = [
{
key: 'letter',
label: '字母',
children: [
'α', 'β', 'γ', 'δ', 'ϵ', 'ε', 'ζ', 'η', 'θ', 'ϑ', 'ι', 'κ', 'λ', 'μ', 'ν', 'ξ', 'π', 'ϖ', 'ρ', 'ϱ', 'σ', 'ς', 'τ', 'υ', 'ϕ', 'φ', 'χ', 'ψ', 'ω',
'Γ', 'Δ', 'Θ', 'Λ', 'Ξ', 'Π', 'Σ', 'Υ', 'Φ', 'Ψ', 'Ω',
'𝐀', '𝐁', '𝐂', '𝐃', '𝐄', '𝐅', '𝐆', '𝐇', '𝐈', '𝐉', '𝐊', '𝐋', '𝐌', '𝐍', '𝐎', '𝐏', '𝐐', '𝐑', '𝐒', '𝐓', '𝐔', '𝐕', '𝐖', '𝐗', '𝐘', '𝐙',
'𝐚', '𝐛', '𝐜', '𝐝', '𝐞', '𝐟', '𝐠', '𝐡', '𝐢', '𝐣', '𝐤', '𝐥', '𝐦', '𝐧', '𝐨', '𝐩', '𝐪', '𝐫', '𝐬', '𝐭', '𝐮', '𝐯', '𝐰', '𝐱', '𝐲', '𝐳',
'𝓐', '𝓑', '𝓒', '𝓓', '𝓔', '𝓕', '𝓖', '𝓗', '𝓘', '𝓙', '𝓚', '𝓛', '𝓜', '𝓝', '𝓞', '𝓟', '𝓠', '𝓡', '𝓢', '𝓣', '𝓤', '𝓥', '𝓦', '𝓧', '𝓨', '𝓩',
'𝓪', '𝓫', '𝓬', '𝓭', '𝓮', '𝓯', '𝓰', '𝓱', '𝓲', '𝓳', '𝓴', '𝓵', '𝓶', '𝓷', '𝓸', '𝓹', '𝓺', '𝓻', '𝓼', '𝓽', '𝓾', '𝓿', '𝔀', '𝔁', '𝔂', '𝔃',
],
},
{
key: 'number',
label: '序号',
children: [
'①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩', '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳',
'⑴', '⑵', '⑶', '⑷', '⑸', '⑹', '⑺', '⑻', '⑼', '⑽', '⑾', '⑿', '⒀', '⒁', '⒂', '⒃', '⒄', '⒅', '⒆', '⒇',
'º', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹', '₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉',
'', 'Ⅱ', 'Ⅲ', 'Ⅳ', '', 'Ⅵ', 'Ⅶ', 'Ⅷ', 'Ⅸ', '', 'Ⅺ', 'Ⅻ', '', '', '', '',
'', 'ⅱ', 'ⅲ', 'ⅳ', '', 'ⅵ', 'ⅶ', 'ⅷ', 'ⅸ', '', 'ⅺ', 'ⅻ', '', '', '', 'ⅿ', 'ↀ', 'ↁ', 'ↂ',
'㊀', '㊁', '㊂', '㊃', '㊄', '㊅', '㊆', '㊇', '㊈', '㊉', '㈠', '㈡', '㈢', '㈣', '㈤', '㈥', '㈦', '㈧', '㈨', '㈩',
'𝟘', '𝟙', '𝟚', '𝟛', '𝟜', '𝟝', '𝟞', '𝟟', '𝟠', '𝟡',
],
},
{
key: 'math',
label: '数学',
children: [
'+', '-', '×', '÷', '=', '~', '¬', '±', '%', '°', 'ǃ', '‰', '‱', '½', '⅓', '⅔', '¼', '¾',
'<', '>', 'l', 'o', 'g', 'l', 'g', 'l', 'n', '⨂', '⨁', '⨄', '⨃', '⨅', '⨆', '√', '∛', '∜', '∝', '∞',
'∟', '∠', '∡', '∢', '∧', '', '∩', '', '∫', '∬', '∭', '∮', '∯', '∰', '∱', '∲', '∳',
'∴', '∵', '', '∽', '∾', '∿', '≃', '≄', '≅', '≆', '≇', '≈', '≊', '≋', '≌', '≍', '≎', '≏', '≐', '≑', '≒', '≓', '≔', '≕',
'≤', '≥', '≦', '≧', '≨', '≩', '≪', '≫', '≺', '≻', '≼', '≽', '≾', '≿', '⊀', '⊁', '⊂', '⊃', '⊄', '⊅', '⊆', '⊇', '⊈', '⊉', '⊊', '⊋', '⊏', '⊐', '⊑', '⊒',
'⊓', '⊔', '⊢', '⊣', '', '⊥', '⊦', '⊧', '⊨', '⊩', '⊪', '⊫', '⊬', '⊭', '⊮', '⊯', '⊲', '⊳', '⊴', '⊵', '⋀', '', '⋂', '', '⋉', '⋊',
'⋋', '⋌', '⟨', '⟩', '⟪', '⟫', '⟮', '⟯', '⧼', '⧽', '⦰',
],
},
{
key: 'arrow',
label: '箭头',
children: [
'←', '↑', '→', '↓', '↔', '↕', '↖', '↗', '↘', '↙', '↚', '↛', '↜', '↝', '↞', '↟', '↠', '↡', '↢', '↣', '↤', '↥', '↦', '↧', '↨',
'↫', '↬', '↭', '↮', '↯', '↰', '↱', '↲', '↳', '↴', '↵', '↶', '↷', '↸', '↹', '↺', '↻', '↼', '↽', '↾', '↿', '⇀', '⇁', '⇂', '⇃',
'⇄', '⇅', '⇆', '⇇', '⇈', '⇉', '⇊', '⇋', '⇌', '⇍', '⇎', '⇏', '⇐', '⇑', '⇒', '⇓', '⇔', '⇕', '⇖', '⇗', '⇘', '⇙', '⇚', '⇛',
'⇜', '⇝', '⇞', '⇟', '⇠', '⇡', '⇢', '⇣', '⇤', '⇥', '⇦', '⇧', '⇨', '⇩', '⇪', '⇫', '⇬', '⇭', '⇮', '⇯', '⇰', '⇱', '⇲', '⇳', '⇴', '⇵',
'⇶', '⇷', '⇸', '⇹', '⇺', '⇻', '⇼', '⇽', '⇾', '⇿',
],
},
{
key: 'graph',
label: '图形',
children: [
'▢', '▣', '▤', '▥', '▦', '▧', '▨', '▩', '▭', '▮', '▯', '▰', '▱', '▲', '▷', '▼', '◁',
'◈', '◉', '◍', '◐', '◑', '◒', '◓', '◔', '◕', '◧', '◨', '◩', '◪', '◫', '◬', '◭', '◮',
],
},
]

View File

@ -1,6 +1,7 @@
export type ToolbarState = 'elAnimation' | 'elStyle' | 'elPosition' | 'slideDesign' | 'slideAnimation' | 'multiPosition'
export type ToolbarState = 'symbol' | 'elAnimation' | 'elStyle' | 'elPosition' | 'slideDesign' | 'slideAnimation' | 'multiPosition'
export const ToolbarStates = {
SYMBOL: 'symbol',
EL_ANIMATION: 'elAnimation',
EL_STYLE: 'elStyle',
EL_POSITION: 'elPosition',

View File

@ -0,0 +1,104 @@
<template>
<div class="symbol-panel">
<div class="tabs">
<div
class="tab"
:class="{ 'active': selectedSymbolKey === item.key }"
v-for="item in symbolPoolList"
:key="item.key"
@click="selectedSymbolKey = item.key"
>{{item.label}}</div>
</div>
<div class="pool">
<div class="symbol-item" v-for="(item, index) in symbolPool" :key="index" @click="selectSymbol(item)">
<div class="symbol">{{item}}</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { SYMBOL_LIST } from '@/configs/symbol'
import emitter, { EmitterEvents } from '@/utils/emitter'
const symbolPoolList = SYMBOL_LIST
export default defineComponent({
name: 'symbol-panel',
setup() {
const selectedSymbolKey = ref(symbolPoolList[0].key)
const symbolPool = computed(() => {
const selectedSymbol = symbolPoolList.find(item => item.key === selectedSymbolKey.value)
return selectedSymbol?.children || []
})
const selectSymbol = (item: string) => {
emitter.emit(EmitterEvents.RICH_TEXT_COMMAND, { command: 'insert', value: item })
}
return {
symbolPoolList,
symbolPool,
selectedSymbolKey,
selectSymbol,
}
},
})
</script>
<style lang="scss" scoped>
.symbol-panel {
height: 100%;
display: flex;
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;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active {
border-bottom: 2px solid $themeColor;
}
}
.pool {
padding: 5px 12px;
margin: 0 -12px;
flex: 1;
font-size: 18px;
@include overflow-overlay();
@include flex-grid-layout();
}
.symbol-item {
@include flex-grid-layout-children(5, 18%);
height: 0;
padding-bottom: 18%;
position: relative;
cursor: pointer;
border: 1px solid $borderColor;
&:hover {
color: $themeColor;
}
.symbol {
@include absolute-0();
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
}
}
}
</style>

View File

@ -18,6 +18,7 @@
<script lang="ts">
import { computed, defineComponent, watch } from 'vue'
import { MutationTypes, useStore } from '@/store'
import { PPTElement } from '@/types/slides'
import { ToolbarState, ToolbarStates } from '@/types/toolbar'
import ElementStylePanel from './ElementStylePanel/index.vue'
@ -26,18 +27,30 @@ import ElementAnimationPanel from './ElementAnimationPanel.vue'
import SlideDesignPanel from './SlideDesignPanel.vue'
import SlideAnimationPanel from './SlideAnimationPanel.vue'
import MultiPositionPanel from './MultiPositionPanel.vue'
import SymbolPanel from './SymbolPanel.vue'
export default defineComponent({
name: 'toolbar',
setup() {
const store = useStore()
const toolbarState = computed(() => store.state.toolbarState)
const handleElement = computed<PPTElement>(() => store.getters.handleElement)
const elementTabs = [
{ label: '样式', value: ToolbarStates.EL_STYLE },
{ label: '位置', value: ToolbarStates.EL_POSITION },
{ label: '动画', value: ToolbarStates.EL_ANIMATION },
]
const elementTabs = computed(() => {
if (handleElement.value.type === 'text') {
return [
{ label: '样式', value: ToolbarStates.EL_STYLE },
{ label: '符号', value: ToolbarStates.SYMBOL },
{ label: '位置', value: ToolbarStates.EL_POSITION },
{ label: '动画', value: ToolbarStates.EL_ANIMATION },
]
}
return [
{ label: '样式', value: ToolbarStates.EL_STYLE },
{ label: '位置', value: ToolbarStates.EL_POSITION },
{ label: '动画', value: ToolbarStates.EL_ANIMATION },
]
})
const slideTabs = [
{ label: '设计', value: ToolbarStates.SLIDE_DESIGN },
{ label: '切换', value: ToolbarStates.SLIDE_ANIMATION },
@ -56,7 +69,7 @@ export default defineComponent({
const currentTabs = computed(() => {
if (!activeElementIdList.value.length) return slideTabs
else if (activeElementIdList.value.length > 1) return multiSelectTabs
return elementTabs
return elementTabs.value
})
watch(currentTabs, () => {
@ -74,6 +87,7 @@ export default defineComponent({
[ToolbarStates.SLIDE_DESIGN]: SlideDesignPanel,
[ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,
[ToolbarStates.MULTI_POSITION]: MultiPositionPanel,
[ToolbarStates.SYMBOL]: SymbolPanel,
}
return panelMap[toolbarState.value] || null
})

View File

@ -204,6 +204,9 @@ export default defineComponent({
const { $from, $to } = editorView.state.selection
editorView.dispatch(editorView.state.tr.removeMark($from.pos, $to.pos))
}
else if (item.command === 'insert' && item.value) {
editorView.dispatch(editorView.state.tr.insertText(item.value))
}
}
editorView.focus()