vue3+ts+tinynce在富文本编辑器菜单栏实现下拉框选择
实现效果
代码:
<script lang="ts" setup>
import Editor from '@tinymce/tinymce-vue'
import tinymce from 'tinymce';
import { getIndicator } from '@/api/data-assets/data-dictory'import {computed, ref} from "vue";
const props = defineProps({input_disabled: {type: Boolean,default: false // 设置默认值为 false},input_content: {type: String,default: '' // 设置默认值为 false},
});
const input_disabled = computed(() => {return props.input_disabled
})
//双向绑定编辑器数据
const input_content = ref("")
//是否禁用--用于工单流转
function handlePromise(promiseList) {return promiseList.map(promise =>promise.then((res) => ({ status: 'ok', res }), (err) => ({ status: 'not ok', err })))
}
Promise.allSettled = function (promiseList) {return Promise.all(handlePromise(promiseList))
}//tinymce选项配置
const initOptions = ref({//挂载点selector: '#edit_input',//模式// inline: true,//语言设置language: "zh-Hans",//自动聚焦auto_focus: true,//只读模式//readonly:true,//空内容时展示placeholder: '正文内容',//引入站外插件external_plugins: {},//解决缓存问题cache_suffix: '?v=1.0.0',//编辑器区域自定义样式content_style: "img {max-width:100%;}",// icons: 'custom',//插件配置plugins: ['wordcount','table','searchreplace','preview','pagebreak','insertdatetime','fullscreen','emoticons','codesample','charmap','autosave','autolink','anchor','advlist', 'autolink', 'image', 'lists', 'preview', 'code'],toolbar1: 'forecolor backcolor|code|bullist|numlist|blockquote|styles|bold italic strikethrough underline|alignleft aligncenter alignright outdent indent |mybutton',toolbar2: ' undo redo |fontfamily fontsize |table|searchreplace|preview|pagebreak|insertdatetime|fullscreen|emoticons|codesample|charmap|restoredraft|anchor|link image | language|parmars',//工具栏模式toolbar_mode:'sliding',//设置插件时间格式insertdatetime_formats: ["%H点%M分", "%Y年%m月%d日"],//保存在localstorage下的文件的保存时间autosave_retention:'10080m',//菜单栏配置menubar: false,//设置工具栏在顶部fixed_toolbar_container: '#edit_input',//宽高设置width: '100%',height: '100%',//设置皮肤skin: 'oxide',//主题设置theme:'silver',//编辑器大小改变resize: false,//隐藏状态栏底部图标branding: false,//init出多个实例时只在该实例上显示菜单栏(多个编辑器时很有用)// event_root: '#edit_input',//隐藏状态栏左侧路径elementpath: false,//允许代码保留注释allow_conditional_comments: true,//字体列表font_formats: '微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif',//指定图片上传接口images_upload_url: '/demo/upimg.php',//后端返回json应该是{ location : "/demo/image/1.jpg" }这种格式//指定图片上传返回的相对路径的基本路径images_upload_base_path: '/demo',//移动端适配mobile: {menubar: false,},//初始化前执行函数setup: function (editor:HTMLElement) {console.log("ID为: " + editor.id + " 的编辑器即将初始化.");console.log(editor)let toggleState = false;editor.ui.registry.addMenuButton('mybutton', {text: '插入指标',fetch: async(callback) => {// 以下为请求接口数据const res = await getIndicator()let items=[]res.data.forEach(element => {items.push({type: 'menuitem',text: element.indicatorName,onAction: () => editor.insertContent(` <em style="text-decoration: underline; color: rgb(53, 152, 219);">#${element.indicatorName+"$"+element.id}</em> `)})});console.log(items)//以下为测试数据// const items = [// {// type: 'menuitem',// text: 'Menu item 1',// onAction: () => editor.insertContent(' <em>You clicked menu item 1!</em>')// },// {// type: 'nestedmenuitem',// text: 'Menu item 2',// icon: 'user',// getSubmenuItems: () => [// {// type: 'menuitem',// text: 'Sub menu item 1',// icon: 'unlock',// onAction: () => editor.insertContent(' <em>You clicked Sub menu item 1!</em>')// },// ]// },// {// type: 'togglemenuitem',// text: 'Toggle menu item',// onAction: () => {// toggleState = !toggleState;// editor.insertContent(' <em>You toggled a menuitem ' + (toggleState ? 'on' : 'off') + '</em>');// },// onSetup: (api) => {// api.setActive(toggleState);// return () => {};// }// }// ];callback(items);}});},//初始化后执行回调init_instance_callback: function (editor:HTMLElement) {console.log("ID为: " + editor.id + " 的编辑器已初始化完成.");}
})defineExpose({input_content,
})</script><template><div class="edit_wrap"><Editortabindex="1"v-model="input_content"id="edit_input":init="initOptions":disabled="input_disabled"/></div>
</template><style lang="scss" scoped>
.edit_wrap {height: 100%;overflow: hidden;display: flex;#edit_input,#edit_outer {width: 100%;flex-grow: 10;align-self: stretch;}
}
</style><style lang="scss">
* {box-sizing: border-box;margin: 0;padding: 0;
}body, html {height: 100vh;
}#app {height: 100%;
}img {max-width: 400px !important;
}</style>
核心逻辑
在工具栏引入工具