feat: advance toolbar

This commit is contained in:
KUN1007 2023-09-04 20:02:23 +08:00
parent 50ced43d20
commit 352f20ec93
9 changed files with 229 additions and 162 deletions

View file

@ -1,25 +1,23 @@
<script setup lang="ts">
import { ref } from 'vue'
import { defineAsyncComponent, ref } from 'vue'
//
import { Icon } from '@iconify/vue'
//
import SwitchButton from './SwitchButton.vue'
//
const EditorSettingsMenu = defineAsyncComponent(
() => import('./EditorSettingsMenu.vue')
)
// css
import 'animate.css'
// store
import { useKUNGalgameEditStore } from '@/store/modules/edit'
import { storeToRefs } from 'pinia'
const { editorHeight } = storeToRefs(useKUNGalgameEditStore())
//
defineProps<{
textCount: number
}>()
//
const isShowSettingsMenu = ref(true)
const isShowSettingsMenu = ref(false)
//
const handelClickSettings = () => {
@ -43,37 +41,8 @@ const handelClickSettings = () => {
<!-- 文字计数 -->
<span class="count">{{ textCount + ` ${$tm('edit.word')}` }}</span>
<Transition
enter-active-class="animate__animated animate__jackInTheBox animate__faster"
leave-active-class="animate__animated animate__rollOut animate__faster"
>
<!-- 设置菜单 -->
<div v-if="isShowSettingsMenu" class="settings-menu">
<!-- 编辑器高度设置 -->
<div class="editor-height-title">
<span> 编辑器高度 </span>
<span>{{ editorHeight }} px</span>
</div>
<div class="editor-height">
<span>300 px</span>
<input
type="range"
min="300"
max="500"
step="1"
v-model="editorHeight"
/>
<span>500 px</span>
</div>
<!-- 是否显示编辑器高级选项 -->
<div class="editor-advance-title">
<span> 高级选项 </span>
<!-- 切换按钮 -->
<SwitchButton />
</div>
</div>
</Transition>
<!-- 设置面板 -->
<EditorSettingsMenu :isShowSettingsMenu="isShowSettingsMenu" />
</div>
</template>
@ -101,37 +70,6 @@ const handelClickSettings = () => {
}
}
.settings-menu {
padding: 10px;
z-index: 1009;
position: absolute;
bottom: 50px;
background-color: var(--kungalgame-white);
border: 1px solid var(--kungalgame-blue-1);
box-shadow: var(--shadow);
border-radius: 5px;
display: flex;
flex-direction: column;
.editor-height-title {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
font-size: 17px;
}
.editor-advance-title {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
font-size: 17px;
}
.editor-height {
margin-bottom: 20px;
}
}
.count {
color: var(--kungalgame-font-color-0);
background-color: var(--kungalgame-trans-white-9);

View file

@ -0,0 +1,146 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
//
import { Icon } from '@iconify/vue'
//
import SwitchButton from './SwitchButton.vue'
// css
import 'animate.css'
// store
import { useKUNGalgameEditStore } from '@/store/modules/edit'
import { storeToRefs } from 'pinia'
// 使 store
const settingsStore = useKUNGalgameEditStore()
const { isShowAdvance } = storeToRefs(settingsStore)
const { editorHeight } = storeToRefs(useKUNGalgameEditStore())
defineProps<{
isShowSettingsMenu: boolean
}>()
//
const isRefreshPage = ref(false)
//
watch(isShowAdvance, () => {
isRefreshPage.value = !isRefreshPage.value
})
const handleRefreshPage = () => location.reload()
</script>
<template>
<Transition
enter-active-class="animate__animated animate__jackInTheBox animate__faster"
leave-active-class="animate__animated animate__rollOut animate__faster"
>
<!-- 设置菜单 -->
<div v-if="isShowSettingsMenu" class="settings-menu">
<!-- 编辑器高度设置 -->
<div class="editor-height-title">
<span> 编辑器高度 </span>
<span>{{ editorHeight }} px</span>
</div>
<div class="editor-height">
<span>300 px</span>
<input
type="range"
min="300"
max="500"
step="1"
v-model="editorHeight"
/>
<span>500 px</span>
</div>
<!-- 是否显示编辑器高级选项 -->
<div class="editor-advance-title">
<div class="editor-advance">
<Transition mode="out-in" name="slide-up">
<span v-if="!isRefreshPage"> 高级编辑模式 </span>
<span
@click="handleRefreshPage"
class="refresh"
v-else-if="isRefreshPage"
>
<span>刷新页面生效</span>
<Icon icon="line-md:rotate-270" />
</span>
</Transition>
</div>
<!-- 切换按钮 -->
<SwitchButton />
</div>
</div>
</Transition>
</template>
<style lang="scss" scoped>
.settings-menu {
padding: 10px;
z-index: 1009;
position: absolute;
bottom: 50px;
background-color: var(--kungalgame-white);
border: 1px solid var(--kungalgame-blue-1);
box-shadow: var(--shadow);
border-radius: 5px;
display: flex;
flex-direction: column;
.editor-height-title {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
font-size: 17px;
}
.editor-advance-title {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
font-size: 17px;
}
}
.editor-height {
margin-bottom: 20px;
}
.editor-advance {
display: flex;
flex-direction: column;
.refresh {
display: flex;
align-items: center;
font-size: 23px;
cursor: pointer;
&:hover {
color: var(--kungalgame-blue-4);
}
span {
margin-right: 10px;
font-size: 17px;
}
}
}
.slide-up-enter-active,
.slide-up-leave-active {
transition: all 0.25s ease-out;
}
.slide-up-enter-from {
opacity: 0;
transform: translateY(30px);
}
.slide-up-leave-to {
opacity: 0;
transform: translateY(-30px);
}
</style>

View file

@ -1,6 +1,7 @@
<!-- KUNGalgame 通用切换按钮 -->
<script setup lang="ts">
import { watch } from 'vue'
// store
import { useKUNGalgameEditStore } from '@/store/modules/edit'
import { storeToRefs } from 'pinia'
@ -9,15 +10,14 @@ import { storeToRefs } from 'pinia'
const settingsStore = useKUNGalgameEditStore()
const { isShowAdvance } = storeToRefs(settingsStore)
// toolbar
const toggleEditorMode = () => {
isShowAdvance.value = !isShowAdvance.value
}
// store store
watch(isShowAdvance, (newValue) => {
isShowAdvance.value = newValue
})
</script>
<template>
<input type="checkbox" id="switch" /><label
@click="toggleEditorMode"
<input type="checkbox" id="switch" v-model="isShowAdvance" /><label
for="switch"
>Toggle</label
>

View file

@ -78,7 +78,5 @@ const handelInput = () => {
/* 标题输入字体大小 */
font-size: 40px;
border: none;
/* 光标样式 */
caret-shape: block;
}
</style>

View file

@ -20,6 +20,7 @@ import { Editor } from '@wangeditor/editor-for-vue'
//
import { IToolbarConfig } from '@wangeditor/editor'
import { Toolbar } from '@wangeditor/editor-for-vue'
import { keysToExclude } from './keysToExclude'
//
const Title = defineAsyncComponent(
@ -38,7 +39,9 @@ import DOMPurify from 'dompurify'
//
import { debounce } from '@/utils/debounce'
const topicData = storeToRefs(useKUNGalgameEditStore())
const { editorHeight, isShowAdvance, isSave, content } = storeToRefs(
useKUNGalgameEditStore()
)
//
const props = defineProps<{
@ -54,7 +57,7 @@ const props = defineProps<{
const editorRef = shallowRef<IDomEditor | undefined>(undefined)
//
const editorHeight = computed(() => `height: ${topicData.editorHeight.value}px`)
const editorHeightStyle = computed(() => `height: ${editorHeight.value}px`)
//
const valueHtml = ref('')
//
@ -82,23 +85,23 @@ const editorConfig: Partial<IEditorConfig> = {
},
}
const keys: string[] = []
//
const toolbarConfig: Partial<IToolbarConfig> = {
excludeKeys: ['uploadVideo'].concat(keys),
// keys
excludeKeys: isShowAdvance.value ? ['uploadVideo'] : keysToExclude,
}
const handleCreated = (editor: IDomEditor) => {
console.log(editor.getAllMenuKeys())
editorRef.value = editor // editor
editor.on('modalOrPanelShow', (modalOrPanel) => {
console.log(modalOrPanel)
})
}
//
onBeforeMount(() => {
if (topicData.isSave.value) {
valueHtml.value = topicData.content.value
if (isSave.value) {
valueHtml.value = content.value
}
})
@ -115,7 +118,7 @@ const handleChange = (editor: IDomEditor) => {
//
const debouncedUpdateContent = debounce(() => {
// xss
topicData.content.value = DOMPurify.sanitize(editor.getHtml())
content.value = DOMPurify.sanitize(editor.getHtml())
}, 1007)
//
@ -149,7 +152,7 @@ const handleChange = (editor: IDomEditor) => {
<!-- 编辑器本体 -->
<Editor
class="wang-editor"
:style="editorHeight"
:style="editorHeightStyle"
v-model="valueHtml"
:defaultConfig="editorConfig"
@onCreated="handleCreated"
@ -162,10 +165,7 @@ const handleChange = (editor: IDomEditor) => {
</div>
<!-- 编辑器 footer -->
<EditorFooter
:textCount="textCount"
:editorHeight="topicData.editorHeight.value"
/>
<EditorFooter :textCount="textCount" :editorHeight="editorHeight" />
</div>
</template>
@ -177,8 +177,7 @@ const handleChange = (editor: IDomEditor) => {
width: 100%;
margin: 0 auto;
z-index: 1008;
background-color: var(--kungalgame-trans-white-5);
backdrop-filter: blur(5px);
background-color: var(--kungalgame-trans-white-2);
}
.toolbar {

View file

@ -1,62 +0,0 @@
;[
'bold',
'underline',
'italic',
'through',
'code',
'sub',
'sup',
'clearStyle',
'color',
'bgColor',
'fontSize',
'fontFamily',
'indent',
'delIndent',
'justifyLeft',
'justifyRight',
'justifyCenter',
'justifyJustify',
'lineHeight',
'insertImage',
'deleteImage',
'editImage',
'viewImageLink',
'imageWidth30',
'imageWidth50',
'imageWidth100',
'divider',
'emotion',
'insertLink',
'editLink',
'unLink',
'viewLink',
'codeBlock',
'blockquote',
'headerSelect',
'header1',
'header2',
'header3',
'header4',
'header5',
'todo',
'redo',
'undo',
'fullScreen',
'enter',
'bulletedList',
'numberedList',
'insertTable',
'deleteTable',
'insertTableRow',
'deleteTableRow',
'insertTableCol',
'deleteTableCol',
'tableHeader',
'tableFullWidth',
'insertVideo',
'uploadVideo',
'editVideoSize',
'uploadImage',
'codeSelectLang',
]

View file

@ -0,0 +1,34 @@
// 编辑器 toolbar 要排除的项目
export const keysToExclude: string[] = [
// 角标
'sub',
'sup',
// 文字精确大小,字体,行高
'fontSize',
'fontFamily',
'lineHeight',
// 文字背景色
'bgColor',
// todo, undo, redo
'todo',
'redo',
'undo',
// 缩进的组
'group-indent',
// 插入视频的组
'group-video',
// 表格
'insertTable',
'deleteTable',
'deleteTableRow',
'insertTableCol',
'deleteTableCol',
'tableHeader',
'tableFullWidth',
// 右键菜单已有的功能
'headerSelect',
'bold',
'bulletedList',
'insertLink',
'group-more-style',
]

View file

@ -27,14 +27,27 @@ u {
text-shadow: none;
}
/* 不显示分割线 */
.w-e-bar-divider {
display: none;
}
a {
color: var(--kungalgame-blue-5);
border-bottom: 1.5px solid var(--kungalgame-trans-white-9);
&:hover {
border-bottom: 1.5px solid var(--kungalgame-blue-5);
}
}
:root {
/* textarea - css vars */
--w-e-textarea-bg-color: var(--kungalgame-white-9);
--w-e-textarea-color: var(--kungalgame-font-color-3);
--w-e-textarea-border-color: var(--kungalgame-blue-1);
--w-e-textarea-border-color: var(--kungalgame-blue-4);
--w-e-textarea-slight-border-color: var(--kungalgame-blue-4);
--w-e-textarea-slight-color: var(--kungalgame-font-color-0);
--w-e-textarea-slight-bg-color: var(--kungalgame-white-9);
--w-e-textarea-slight-bg-color: var(--kungalgame-trans-blue-0);
--w-e-textarea-selected-border-color: var(--kungalgame-blue-1);
/* 选中的元素,如选中了分割线 */
--w-e-textarea-handler-bg-color: var(--kungalgame-blue-4);

View file

@ -28,7 +28,8 @@ onMounted(() => {
<style lang="scss" scoped>
/* 内容区右侧的话题展示区 */
.w-e-text-container {
width: 82%;
/** 100 + 20 + 20 + 1 = 141px */
width: calc(100% - 141px);
font-size: 15px;
padding: 17px;
border-left: 1px solid var(--kungalgame-blue-1);