Add File
This commit is contained in:
197
frontend/src/views/dashboard/components/sq-text/index.vue
Normal file
197
frontend/src/views/dashboard/components/sq-text/index.vue
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<template>
|
||||||
|
<div class="rich-main-class" :class="{ 'edit-model': configItem.editing }" draggable="false">
|
||||||
|
<div
|
||||||
|
:class="{ 'rich-text-empty': true, 'layer-hidden': !isDisabled || configItem.propValue }"
|
||||||
|
@keydown.stop
|
||||||
|
@keyup.stop
|
||||||
|
@mousedown.stop
|
||||||
|
@dblclick.stop="setEdit"
|
||||||
|
>
|
||||||
|
{{ t('dashboard.rich_text_tips') }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
draggable="false"
|
||||||
|
:class="{ 'custom-text-content': true, 'preview-text': true, 'layer-hidden': !isDisabled }"
|
||||||
|
@keydown.stop
|
||||||
|
@keyup.stop
|
||||||
|
@mousedown.stop
|
||||||
|
@dblclick.stop="setEdit"
|
||||||
|
v-html="configItem.propValue"
|
||||||
|
></div>
|
||||||
|
<editor
|
||||||
|
:id="tinymceId"
|
||||||
|
v-model="configItem.propValue"
|
||||||
|
draggable="false"
|
||||||
|
:class="{ 'custom-text-content': true, 'layer-hidden': isDisabled }"
|
||||||
|
:init="init"
|
||||||
|
></editor>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import tinymce from 'tinymce/tinymce'
|
||||||
|
import Editor from '@tinymce/tinymce-vue'
|
||||||
|
import 'tinymce/icons/default'
|
||||||
|
import 'tinymce/plugins/link'
|
||||||
|
import '@npkg/tinymce-plugins/letterspacing'
|
||||||
|
|
||||||
|
import { computed, nextTick, type PropType, reactive, toRefs } from 'vue'
|
||||||
|
import { onMounted } from 'vue'
|
||||||
|
import type { CanvasItem } from '@/utils/canvas.ts'
|
||||||
|
import { dashboardStoreWithOut } from '@/stores/dashboard/dashboard.ts'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const dashboardStore = dashboardStoreWithOut()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
configItem: {
|
||||||
|
type: Object as PropType<CanvasItem>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const { configItem } = toRefs(props)
|
||||||
|
const tinymceId = 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||||
|
const init = reactive({
|
||||||
|
base_url: '/tinymce', // 指向 public/tinymce 目录
|
||||||
|
suffix: '.min',
|
||||||
|
selector: tinymceId,
|
||||||
|
language: 'zh_CN',
|
||||||
|
skin: 'oxide',
|
||||||
|
plugins: 'link letterspacing', // 插件
|
||||||
|
// 工具栏
|
||||||
|
toolbar:
|
||||||
|
'fontfamily fontsize | |forecolor backcolor bold italic letterspacing |underline strikethrough link lineheight| formatselect | alignleft aligncenter alignright |',
|
||||||
|
toolbar_location: '/',
|
||||||
|
font_family_formats:
|
||||||
|
'微软雅黑=Microsoft YaHei;宋体=SimSun;黑体=SimHei;仿宋=FangSong;华文黑体=STHeiti;华文楷体=STKaiti;华文宋体=STSong;华文仿宋=STFangsong;Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings',
|
||||||
|
font_size_formats:
|
||||||
|
'12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 42px 48px 56px 72px 80px 90px 100px 110px 120px 140px 150px 170px 190px 210px', // 字体大小
|
||||||
|
menubar: false,
|
||||||
|
placeholder: '',
|
||||||
|
inline: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const isDisabled = computed(() => props.disabled || !configItem.value.editing)
|
||||||
|
|
||||||
|
const setEdit = () => {
|
||||||
|
configItem.value.editing = true
|
||||||
|
dashboardStore.setCurComponent(configItem.value)
|
||||||
|
nextTick(() => {
|
||||||
|
editCursor()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const editCursor = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const myDiv = document.getElementById(tinymceId)
|
||||||
|
// Focus the cursor on the end of the text
|
||||||
|
const range = document.createRange()
|
||||||
|
const sel = window.getSelection()
|
||||||
|
if (myDiv && myDiv.childNodes) {
|
||||||
|
range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1], 1)
|
||||||
|
range.collapse(false)
|
||||||
|
if (sel) {
|
||||||
|
sel.removeAllRanges()
|
||||||
|
sel.addRange(range)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// For some browsers, it may be necessary to set the cursor to the end in another way
|
||||||
|
if (myDiv && myDiv.focus) {
|
||||||
|
myDiv.focus()
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
tinymce.init({})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped lang="less">
|
||||||
|
.edit-model {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rich-main-class {
|
||||||
|
display: flex;
|
||||||
|
font-size: initial;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto !important;
|
||||||
|
position: relative;
|
||||||
|
padding: 12px !important;
|
||||||
|
div::-webkit-scrollbar {
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
}
|
||||||
|
.rich-text-empty {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% - 24px);
|
||||||
|
height: calc(100% - 24px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
z-index: 10;
|
||||||
|
color: rgba(100, 106, 115, 1);
|
||||||
|
}
|
||||||
|
div::-webkit-scrollbar {
|
||||||
|
width: 0px !important;
|
||||||
|
height: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ol) {
|
||||||
|
display: block !important;
|
||||||
|
list-style-type: decimal;
|
||||||
|
margin-block-start: 1em !important;
|
||||||
|
margin-block-end: 1em !important;
|
||||||
|
margin-inline-start: 0px !important;
|
||||||
|
margin-inline-end: 0px !important;
|
||||||
|
padding-inline-start: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(ul) {
|
||||||
|
display: block !important;
|
||||||
|
list-style-type: disc;
|
||||||
|
margin-block-start: 1em !important;
|
||||||
|
margin-block-end: 1em !important;
|
||||||
|
margin-inline-start: 0px !important;
|
||||||
|
margin-inline-end: 0px !important;
|
||||||
|
padding-inline-start: 40px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(li) {
|
||||||
|
margin-left: 20px;
|
||||||
|
display: list-item !important;
|
||||||
|
text-align: -webkit-match-parent !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-text-content {
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
outline: none !important;
|
||||||
|
border: none !important;
|
||||||
|
margin: 2px;
|
||||||
|
cursor: text;
|
||||||
|
p {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer-hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-text {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user