feat: QuillEditor footer help slot
This commit is contained in:
parent
051a031831
commit
b599ac10c6
|
@ -78,6 +78,7 @@ const messageClass = (type: string): string => {
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
span {
|
span {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineAsyncComponent, ref } from 'vue'
|
import { computed, defineAsyncComponent, ref } from 'vue'
|
||||||
|
|
||||||
// 导入路由
|
// 导入路由
|
||||||
import { useRouter } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
|
||||||
// 引入图标字体
|
// 引入图标字体
|
||||||
import { Icon } from '@iconify/vue'
|
import { Icon } from '@iconify/vue'
|
||||||
|
@ -11,30 +10,32 @@ import { Icon } from '@iconify/vue'
|
||||||
const EditorSettingsMenu = defineAsyncComponent(
|
const EditorSettingsMenu = defineAsyncComponent(
|
||||||
() => import('./EditorSettingsMenu.vue')
|
() => import('./EditorSettingsMenu.vue')
|
||||||
)
|
)
|
||||||
|
|
||||||
// 引入 css 动画
|
// 引入 css 动画
|
||||||
import 'animate.css'
|
import 'animate.css'
|
||||||
|
|
||||||
// 接受传入的编辑器计数
|
// 导入编辑话题的 store
|
||||||
defineProps<{
|
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||||
textCount: number
|
import { useKUNGalgameTopicStore } from '@/store/modules/topic'
|
||||||
}>()
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
const router = useRouter()
|
// 话题编辑界面 store
|
||||||
|
const { textCount } = storeToRefs(useKUNGalgameEditStore())
|
||||||
|
// 话题界面的 store,用于回复
|
||||||
|
const { replyDraft } = storeToRefs(useKUNGalgameTopicStore())
|
||||||
|
|
||||||
|
// 当前的路由
|
||||||
|
const route = useRoute()
|
||||||
|
// 当前页面路由的名字
|
||||||
|
const routeName = computed(() => route.name as string)
|
||||||
|
|
||||||
|
const textCountNumber = computed(() =>
|
||||||
|
routeName.value === 'Edit' ? textCount.value : replyDraft.value.textCount
|
||||||
|
)
|
||||||
|
|
||||||
// 是否显示编辑器设置面板
|
// 是否显示编辑器设置面板
|
||||||
const isShowSettingsMenu = ref(false)
|
const isShowSettingsMenu = ref(false)
|
||||||
// 设置面板被激活后的样式
|
// 设置面板被激活后的样式
|
||||||
const settingsPanelActive = ref('')
|
const settingsPanelActive = ref('')
|
||||||
// 根据鼠标的坐标调整背景色
|
|
||||||
const x = ref(0)
|
|
||||||
// 是否显示信息提示
|
|
||||||
const isShowInfo = ref(false)
|
|
||||||
|
|
||||||
// 当鼠标移动时
|
|
||||||
const onMousemove = (e: MouseEvent) => {
|
|
||||||
x.value = e.clientX
|
|
||||||
}
|
|
||||||
|
|
||||||
// 点击设置按钮
|
// 点击设置按钮
|
||||||
const handelClickSettings = () => {
|
const handelClickSettings = () => {
|
||||||
|
@ -59,33 +60,11 @@ const handelClickSettings = () => {
|
||||||
<Icon icon="uiw:setting-o" />
|
<Icon icon="uiw:setting-o" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="help" @click="isShowInfo = true">
|
<slot name="help" />
|
||||||
<Icon icon="line-md:question-circle" />
|
|
||||||
</span>
|
|
||||||
<div
|
|
||||||
v-if="isShowInfo"
|
|
||||||
@mousemove="onMousemove"
|
|
||||||
@mouseleave="isShowInfo = false"
|
|
||||||
class="info"
|
|
||||||
:style="{ backgroundColor: `hsl(${x}, 77%, 77%)` }"
|
|
||||||
>
|
|
||||||
<ul>
|
|
||||||
<li>{{ $tm('edit.help1') }}</li>
|
|
||||||
<li>{{ $tm('edit.help2') }}</li>
|
|
||||||
<li>{{ $tm('edit.help3') }}</li>
|
|
||||||
<li>{{ $tm('edit.help4') }}</li>
|
|
||||||
<li>
|
|
||||||
{{ $tm('edit.help5') }}
|
|
||||||
<span @click="router.push('/contact')">
|
|
||||||
{{ $tm('edit.contact') }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 文字计数 -->
|
<!-- 文字计数 -->
|
||||||
<span class="count">{{ textCount + ` ${$tm('edit.word')}` }}</span>
|
<span class="count">{{ textCountNumber + ` ${$tm('edit.word')}` }}</span>
|
||||||
|
|
||||||
<!-- 设置面板 -->
|
<!-- 设置面板 -->
|
||||||
<EditorSettingsMenu :isShowSettingsMenu="isShowSettingsMenu" />
|
<EditorSettingsMenu :isShowSettingsMenu="isShowSettingsMenu" />
|
||||||
|
|
|
@ -28,11 +28,6 @@ const route = useRoute()
|
||||||
// 当前页面路由的名字
|
// 当前页面路由的名字
|
||||||
const routeName = computed(() => route.name as string)
|
const routeName = computed(() => route.name as string)
|
||||||
|
|
||||||
// 编辑器的模式
|
|
||||||
const editorMode = computed(() =>
|
|
||||||
routeName.value === 'Edit' ? mode.value : replyDraft.value.mode
|
|
||||||
)
|
|
||||||
|
|
||||||
// 是否显示刷新页面
|
// 是否显示刷新页面
|
||||||
const isRefreshPage = ref(false)
|
const isRefreshPage = ref(false)
|
||||||
|
|
||||||
|
@ -101,13 +96,24 @@ const handleRefreshPage = () => location.reload()
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 切换按钮 -->
|
<!-- 编辑界面切换按钮 -->
|
||||||
<select class="select" v-model="editorMode">
|
<select class="select" v-if="routeName === 'Edit'" v-model="mode">
|
||||||
<option value="minimal">{{ $tm('edit.minimal') }}</option>
|
<option value="minimal">{{ $tm('edit.minimal') }}</option>
|
||||||
<option value="">{{ $tm('edit.default') }}</option>
|
<option value="">{{ $tm('edit.default') }}</option>
|
||||||
<option value="essential">{{ $tm('edit.essential') }}</option>
|
<option value="essential">{{ $tm('edit.essential') }}</option>
|
||||||
<option value="full">{{ $tm('edit.full') }}</option>
|
<option value="full">{{ $tm('edit.full') }}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- 回复面板切换按钮 -->
|
||||||
|
<select
|
||||||
|
class="select"
|
||||||
|
v-if="routeName === 'Topic'"
|
||||||
|
v-model="replyDraft.mode"
|
||||||
|
>
|
||||||
|
<option value="minimal">{{ $tm('edit.minimal') }}</option>
|
||||||
|
<option value="">{{ $tm('edit.default') }}</option>
|
||||||
|
<option value="essential">{{ $tm('edit.essential') }}</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 是否显示热门关键词 -->
|
<!-- 是否显示热门关键词 -->
|
||||||
|
|
131
src/components/quill-editor/Help.vue
Normal file
131
src/components/quill-editor/Help.vue
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
// 全局消息组件(顶部)
|
||||||
|
import message from '@/components/alert/Message'
|
||||||
|
|
||||||
|
// 导入路由
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
// 引入图标字体
|
||||||
|
import { Icon } from '@iconify/vue'
|
||||||
|
|
||||||
|
// 引入 css 动画
|
||||||
|
import 'animate.css'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
// 当前的路由
|
||||||
|
const route = useRoute()
|
||||||
|
// 当前页面路由的名字
|
||||||
|
const routeName = computed(() => route.name as string)
|
||||||
|
|
||||||
|
// 根据鼠标的坐标调整背景色
|
||||||
|
const x = ref(0)
|
||||||
|
// 是否显示信息提示
|
||||||
|
const isShowInfo = ref(false)
|
||||||
|
|
||||||
|
// 当鼠标移动时
|
||||||
|
const onMousemove = (e: MouseEvent) => {
|
||||||
|
x.value = e.clientX
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击帮助
|
||||||
|
const handleClickHelp = () => {
|
||||||
|
if (routeName.value === 'Edit') {
|
||||||
|
isShowInfo.value = true
|
||||||
|
} else {
|
||||||
|
const helpHtmlEN = `<p>You can click on the left settings to adjust the editor's mode.</p>
|
||||||
|
<p>We recommend finishing your text before formatting.</p>
|
||||||
|
<p>The website's code is handwritten, and errors are inevitable.</p>
|
||||||
|
<p>If you encounter any errors, please <a style="color: var(--kungalgame-blue-4); border-bottom: 2px solid var(--kungalgame-blue-4);" href="/contact">Contact Us</a>.</p>`
|
||||||
|
const helpHtmlCN = `<p>您可以点击左侧的设置调整编辑器的模式</p>
|
||||||
|
<p>我们建议您写完文本再进行格式化</p>
|
||||||
|
<p>网站的代码是手写的,错误在所难免</p>
|
||||||
|
<p>如果您遇到错误,请<a style="color: var(--kungalgame-blue-4); border-bottom: 2px solid var(--kungalgame-blue-4);" href="/contact">联系我们</a></p>`
|
||||||
|
|
||||||
|
message(helpHtmlEN, helpHtmlCN, 'info', 5000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="help">
|
||||||
|
<div class="title" @click="handleClickHelp">
|
||||||
|
<span><Icon icon="line-md:question-circle" /></span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="isShowInfo"
|
||||||
|
@mousemove="onMousemove"
|
||||||
|
@mouseleave="isShowInfo = false"
|
||||||
|
class="info"
|
||||||
|
:style="{ backgroundColor: `hsl(${x}, 77%, 77%)` }"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li>{{ $tm('edit.help1') }}</li>
|
||||||
|
<li>{{ $tm('edit.help2') }}</li>
|
||||||
|
<li>{{ $tm('edit.help3') }}</li>
|
||||||
|
<li>{{ $tm('edit.help4') }}</li>
|
||||||
|
<li>
|
||||||
|
{{ $tm('edit.help5') }}
|
||||||
|
<span @click="router.push('/contact')">
|
||||||
|
{{ $tm('edit.contact') }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.help {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: 20px;
|
||||||
|
color: var(--kungalgame-font-color-1);
|
||||||
|
font-size: 23px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
span {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
padding: 3px;
|
||||||
|
color: var(--kungalgame-font-color-2);
|
||||||
|
position: absolute;
|
||||||
|
left: 200px;
|
||||||
|
transition: 0.3s background-color ease;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 100px;
|
||||||
|
ul {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background-color: var(--kungalgame-white);
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
li {
|
||||||
|
&::before {
|
||||||
|
content: '❆ ';
|
||||||
|
color: var(--kungalgame-pink-3);
|
||||||
|
}
|
||||||
|
cursor: default;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 27px;
|
||||||
|
span {
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--kungalgame-blue-4);
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -18,6 +18,8 @@ const Title = defineAsyncComponent(
|
||||||
|
|
||||||
// 导入 Footer
|
// 导入 Footer
|
||||||
import EditorFooter from './EditorFooter.vue'
|
import EditorFooter from './EditorFooter.vue'
|
||||||
|
// Footer 的插槽
|
||||||
|
import Help from './Help.vue'
|
||||||
|
|
||||||
// 导入编辑话题的 store
|
// 导入编辑话题的 store
|
||||||
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
import { useKUNGalgameEditStore } from '@/store/modules/edit'
|
||||||
|
@ -79,11 +81,6 @@ const editorMode = computed(() =>
|
||||||
routeName.value === 'Edit' ? mode.value : replyDraft.value.mode
|
routeName.value === 'Edit' ? mode.value : replyDraft.value.mode
|
||||||
)
|
)
|
||||||
|
|
||||||
// 编辑器的文字计数,根据路由的名字确定
|
|
||||||
const textCountNumber = computed(() =>
|
|
||||||
routeName.value === 'Edit' ? textCount.value : replyDraft.value.textCount
|
|
||||||
)
|
|
||||||
|
|
||||||
// 编辑器的工具栏是否显示
|
// 编辑器的工具栏是否显示
|
||||||
const isShowEditorToolbar = computed(() =>
|
const isShowEditorToolbar = computed(() =>
|
||||||
props.isShowToolbar ? 'block' : 'none'
|
props.isShowToolbar ? 'block' : 'none'
|
||||||
|
@ -152,7 +149,11 @@ const handleTextChange = async () => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 编辑器 footer -->
|
<!-- 编辑器 footer -->
|
||||||
<EditorFooter :textCount="textCountNumber" />
|
<EditorFooter>
|
||||||
|
<template #help>
|
||||||
|
<Help />
|
||||||
|
</template>
|
||||||
|
</EditorFooter>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,8 @@ interface ReplyDraft {
|
||||||
*/
|
*/
|
||||||
editorHeight: number
|
editorHeight: number
|
||||||
textCount: number
|
textCount: number
|
||||||
mode: '' | 'essential' | 'minimal' | 'full'
|
// 这里仅支持三种模式
|
||||||
|
mode: '' | 'essential' | 'minimal'
|
||||||
theme: 'snow' | 'bubble'
|
theme: 'snow' | 'bubble'
|
||||||
// 是否显示热门关键词
|
// 是否显示热门关键词
|
||||||
isShowHotKeywords: boolean
|
isShowHotKeywords: boolean
|
||||||
|
@ -105,7 +106,7 @@ export const useKUNGalgameTopicStore = defineStore({
|
||||||
replyDraft: {
|
replyDraft: {
|
||||||
editorHeight: 200,
|
editorHeight: 200,
|
||||||
textCount: 0,
|
textCount: 0,
|
||||||
mode: '',
|
mode: 'minimal',
|
||||||
theme: 'snow',
|
theme: 'snow',
|
||||||
isShowHotKeywords: true,
|
isShowHotKeywords: true,
|
||||||
|
|
||||||
|
|
|
@ -286,4 +286,10 @@ onBeforeMount(() => {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.content-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue