clay commit : tinymce编辑器集成完毕
This commit is contained in:
@@ -128,6 +128,19 @@ export const constantRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/navigation',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: 'edit/:refId/:navId',
|
||||
component: (resolve) => require(['@/views/sist/navigation/articleEdit'], resolve),
|
||||
name: 'navigationEdit',
|
||||
meta: { title: '编辑详情' }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/article',
|
||||
component: Layout,
|
||||
|
||||
@@ -64,12 +64,7 @@
|
||||
|
||||
<script>
|
||||
import {approve, getArticle, rejected} from "@/api/sist/article";
|
||||
import Editor from '@/views/utils/Editor'
|
||||
import {parseTime} from "@/utils/hcy";
|
||||
export default {
|
||||
components: {
|
||||
Editor
|
||||
},
|
||||
name: "approve",
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :offset="1" :span="22">
|
||||
<Editor v-model="formData.content" :height="800"/>
|
||||
<TinymceEditor v-model="formData.content"></TinymceEditor>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
@@ -155,7 +155,8 @@
|
||||
</template>
|
||||
<script>
|
||||
// import ArticleFile from './ArticleFile'
|
||||
import Editor from '@/views/utils/Editor'
|
||||
// import Editor from '@/views/utils/Editor'
|
||||
import TinymceEditor from '@/views/utils/tinymce/Tinymce'
|
||||
import {updateArticle, getArticle, drafts, getArticleType, getArticleApprove} from "@/api/sist/article";
|
||||
import {Message} from "element-ui";
|
||||
import UploadFile from '@/views/utils/uploadFile.vue';
|
||||
@@ -163,9 +164,10 @@ import { getArticleNav } from '../../../../api/sist/article'
|
||||
import { getToken } from '../../../../utils/auth'
|
||||
import { addFile, delFile } from '../../../../api/sist/file'
|
||||
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Editor,
|
||||
TinymceEditor,
|
||||
UploadFile,
|
||||
// ArticleFile
|
||||
},
|
||||
|
||||
88
ebts-ui/src/views/sist/navigation/articleEdit.vue
Normal file
88
ebts-ui/src/views/sist/navigation/articleEdit.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div class="editor">
|
||||
<el-form :model="formData" size="medium" label-width="100px">
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!-- <el-form-item label="详情标题" prop="title">-->
|
||||
<el-form-item label="详情标题">
|
||||
<el-input v-model="formData.title" placeholder="请输入详情标题" clearable :style="{width: '100%'}">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :offset="1" :span="22">
|
||||
<Editor ref="editor" v-model="formData.content" :height="500"/>
|
||||
<!-- <CodeEdit ref="codeEdit" v-model="formData.content" :height="500"/>-->
|
||||
<!-- <CustomEditor v-model="formData.content" :height="500"/>-->
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24" class="save">
|
||||
<el-form-item size="large">
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getDetails, updateDetails } from '../../../api/sist/navigation'
|
||||
import Editor from '@/views/utils/tinymce/Tinymce'
|
||||
export default {
|
||||
name: 'articleEdit',
|
||||
components: {
|
||||
Editor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
title: '',
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
let refId = this.$route.params && this.$route.params.refId;
|
||||
let navId = this.$route.params && this.$route.params.navId;
|
||||
this.handleUpdateDetails(refId)
|
||||
},
|
||||
methods:{
|
||||
handleUpdateDetails(id) {
|
||||
this.formData = {
|
||||
id: id,
|
||||
title: '',
|
||||
content: ''
|
||||
}
|
||||
getDetails(id).then(res => {
|
||||
if (res.data){
|
||||
this.formData = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
save() {
|
||||
let that = this
|
||||
updateDetails(this.formData).then(res => {
|
||||
that.msgSuccess('修改成功')
|
||||
that.close()
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.$store.dispatch("tagsView/delView", this.$route);
|
||||
this.$router.push({path: "/sist/navigation/", query: {t: Date.now()}})
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.save {
|
||||
//text-align: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.editor{
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -72,14 +72,14 @@
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdateDetails(scope.row.refId)"
|
||||
@click="handleUpdateDetails(scope.row.refId,scope.row.id)"
|
||||
>修改中文详情
|
||||
</el-button>
|
||||
<el-button v-show="scope.row.type == '1'"
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdateDetails(scope.row.enRefId)"
|
||||
@click="handleUpdateDetails(scope.row.enRefId,scope.row.id)"
|
||||
>修改英文详情
|
||||
</el-button>
|
||||
<el-button v-show="scope.row.pid != 0"
|
||||
@@ -250,7 +250,8 @@ import {
|
||||
} from '@/api/sist/navigation'
|
||||
import Treeselect from '@riophae/vue-treeselect'
|
||||
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
|
||||
import Editor from '@/views/utils/Editor'
|
||||
// import Editor from '@/views/utils/Editor'
|
||||
import Editor from '@/views/utils/tinymce/Tinymce'
|
||||
import CodeEdit from '@/views/utils/CodeEdit'
|
||||
import UploadFile from '@/views/utils/uploadFile'
|
||||
import { getArticleNav } from '../../../api/sist/article'
|
||||
@@ -473,16 +474,17 @@ export default {
|
||||
this.form.type = '0'
|
||||
this.title = '添加下级导航'
|
||||
},
|
||||
handleUpdateDetails(id) {
|
||||
this.detailsShow = true
|
||||
this.formData = {
|
||||
id: id,
|
||||
title: '',
|
||||
content: ''
|
||||
}
|
||||
getDetails(id).then(res => {
|
||||
this.formData = res.data
|
||||
})
|
||||
handleUpdateDetails(refId,navId) {
|
||||
this.$router.push('/navigation/edit/' + refId+'/'+navId)
|
||||
// this.detailsShow = true
|
||||
// this.formData = {
|
||||
// id: id,
|
||||
// title: '',
|
||||
// content: ''
|
||||
// }
|
||||
// getDetails(id).then(res => {
|
||||
// this.formData = res.data
|
||||
// })
|
||||
},
|
||||
code(){
|
||||
let html = this.$refs.editor.getHtml()
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="editor" :style="styles" ref="editor"></div>
|
||||
<!-- <div class="code">-->
|
||||
<!-- <el-button @click="openCode">源码</el-button>-->
|
||||
<!-- </div>-->
|
||||
|
||||
|
||||
<el-dialog title="编辑详情" :visible="codeShow" width="1100px" :close-on-click-modal="false" @close="codeShow = false"
|
||||
append-to-body>
|
||||
<textarea
|
||||
class="textarea"
|
||||
rows="50"
|
||||
cols="50"
|
||||
|
||||
v-model="code"></textarea>
|
||||
|
||||
<el-button @click="codeSuccess">完成</el-button>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Editor from 'wangeditor'
|
||||
import { htmlFormat } from './fromat'
|
||||
import { getToken } from '../../utils/auth'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Editor',
|
||||
props: {
|
||||
/* 编辑器的内容 */
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
/* 最小高度 */
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
meanArray: {
|
||||
// 自定义菜单
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
},
|
||||
|
||||
computed: {
|
||||
styles() {
|
||||
let style = {}
|
||||
if (this.minHeight) {
|
||||
style.minHeight = `${this.minHeight}px`
|
||||
}
|
||||
if (this.height) {
|
||||
style.height = `${this.height + 50}px`
|
||||
}
|
||||
return style
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: function(value) {
|
||||
if (value !== this.editor.txt.html()) {
|
||||
this.editor.txt.html(this.value)
|
||||
}
|
||||
}
|
||||
// value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
code: null,
|
||||
codeShow: false,
|
||||
// 默认有这么多菜单,meanArray有值以meanArray为准
|
||||
defaultMeanus: [
|
||||
'head',
|
||||
'bold',
|
||||
'fontSize',
|
||||
'fontName',
|
||||
'italic',
|
||||
'underline',
|
||||
'strikeThrough',
|
||||
'indent',
|
||||
'lineHeight',
|
||||
'foreColor',
|
||||
'backColor',
|
||||
'link',
|
||||
'list',
|
||||
'justify',
|
||||
'quote',
|
||||
'emoticon',
|
||||
'image',
|
||||
'video',
|
||||
'table',
|
||||
'code',
|
||||
'splitLine',
|
||||
'undo',
|
||||
'redo'
|
||||
],
|
||||
editor: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
|
||||
|
||||
pack(s){
|
||||
s = s.replace(/\/\*(.|\n)*?\*\//g, "");
|
||||
s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
|
||||
s = s.replace(/\,[\s\.\#\d]*\{/g, "{");
|
||||
s = s.replace(/;\s*;/g, ";");
|
||||
s = s.replace(/;\s*}/g, "}");
|
||||
s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
|
||||
return (s == null) ? "" : s[1];
|
||||
},
|
||||
|
||||
openCode() {
|
||||
this.code = null
|
||||
this.code = htmlFormat(this.value)
|
||||
// this.code = this.value.replace(/</g, "<").replace(/>/g, ">").replace(/ /g, " ")
|
||||
// console.log(this.code,"this.code)")
|
||||
// let text = this.editor.txt.text().replace(/</ig, "<").replace(/>/ig, ">").replace(/ /ig, " ")
|
||||
// console.log(text,"text")
|
||||
this.codeShow = true
|
||||
},
|
||||
codeSuccess(){
|
||||
console.log(this.code)
|
||||
|
||||
|
||||
// let packer = new Packer;
|
||||
// let output = packer.pack(this.value, 0, 0);
|
||||
// console.log(output, "output")
|
||||
// let output= packageFormat(this.code)
|
||||
// this.setHtml(output)
|
||||
// this.editor.dangerouslyInsertHtml(this.code)
|
||||
this.code = null
|
||||
this.codeShow = false
|
||||
},
|
||||
init() {
|
||||
const _this = this
|
||||
this.editor = new Editor(this.$refs.editor)
|
||||
this.editor.config.uploadImgAccept = ['doc', 'docx', 'png', 'img', 'gif', 'bmp', 'webp']
|
||||
// this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
|
||||
// this.editor.config.uploadImgServer = process.env.VUE_APP_BASE_API + "/web/images"
|
||||
// this.editor.config.uploadFileName = "file"
|
||||
// this.editor.config.uploadImgParams= {
|
||||
//
|
||||
// }
|
||||
|
||||
this.editor.config.customUploadImg = function (resultFiles, insertImgFn) {
|
||||
// resultFiles 是 input 中选中的文件列表
|
||||
// insertImgFn 是获取图片 url 后,插入到编辑器的方法
|
||||
let forms = new FormData()
|
||||
let configs = {
|
||||
headers:{
|
||||
'Content-Type':'multipart/form-data',
|
||||
Authorization: getToken()
|
||||
}
|
||||
};
|
||||
forms.append('file',resultFiles[0])
|
||||
|
||||
axios.post(
|
||||
process.env.VUE_APP_BASE_API + "/sist/article/images",
|
||||
forms ,configs).then(res=>{
|
||||
console.log(res)
|
||||
let img = "<p></p><img src='"+res.data.data.href+"' alt='"+res.data.data.url+"'></p>"
|
||||
_this.setHtml(_this.getHtml() + img)
|
||||
})
|
||||
// 上传图片,返回结果,将图片插入到编辑器中
|
||||
}
|
||||
this.editor.config.height = this.height
|
||||
this.editor.config.pasteFilterStyle = false
|
||||
this.editor.config.zIndex = 10
|
||||
// this.editor.config.uploadImgHooks = {
|
||||
// customInsert: function (insertImg, result, editor2) {
|
||||
// // uploadResult(result);
|
||||
// console.log(result)
|
||||
// insertImg(result.data.url);
|
||||
// }
|
||||
// }
|
||||
this.setMenus() // 设置菜单
|
||||
this.editor.config.onchange = (html) => {
|
||||
_this.$emit('change', html) // 将内容同步到父组件中
|
||||
}
|
||||
this.editor.create() // 创建编辑器
|
||||
},
|
||||
setMenus() {
|
||||
// 设置菜单
|
||||
if (this.meanArray) {
|
||||
this.editor.config.menus = this.meanArray
|
||||
} else {
|
||||
this.editor.config.menus = this.defaultMeanus
|
||||
}
|
||||
},
|
||||
getHtml() {
|
||||
// 得到文本内容
|
||||
return this.editor.txt.html()
|
||||
},
|
||||
setHtml(txt) {
|
||||
// 设置富文本里面的值
|
||||
// this.editor.txt.html(txt)
|
||||
this.editor.txt.text(txt)
|
||||
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const that = this
|
||||
that.$nextTick(function() {
|
||||
that.init()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.editor {
|
||||
z-index: 1 !important;
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.code {
|
||||
margin-top: 3rem;
|
||||
|
||||
}
|
||||
.textarea{
|
||||
width: 1036px;
|
||||
height: 750px;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,11 +1,33 @@
|
||||
<template>
|
||||
<div class="editor" :style="styles" ref="editor"></div>
|
||||
<div>
|
||||
<div class="editor" :style="styles" ref="editor"></div>
|
||||
<!-- <div class="code">-->
|
||||
<!-- <el-button @click="openCode">源码</el-button>-->
|
||||
<!-- </div>-->
|
||||
|
||||
|
||||
<el-dialog title="编辑详情" :visible="codeShow" width="1100px" :close-on-click-modal="false" @close="codeShow = false"
|
||||
append-to-body>
|
||||
<textarea
|
||||
class="textarea"
|
||||
rows="50"
|
||||
cols="50"
|
||||
|
||||
v-model="code"></textarea>
|
||||
|
||||
<el-button @click="codeSuccess">完成</el-button>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Editor from 'wangeditor'
|
||||
import { htmlFormat } from './fromat'
|
||||
import { getToken } from '../../utils/auth'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: "Editor",
|
||||
name: 'Editor',
|
||||
props: {
|
||||
/* 编辑器的内容 */
|
||||
value: {
|
||||
@@ -15,12 +37,12 @@ export default {
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
/* 最小高度 */
|
||||
minHeight: {
|
||||
type: Number,
|
||||
default: null,
|
||||
default: null
|
||||
},
|
||||
meanArray: {
|
||||
// 自定义菜单
|
||||
@@ -35,27 +57,28 @@ export default {
|
||||
|
||||
computed: {
|
||||
styles() {
|
||||
let style = {};
|
||||
let style = {}
|
||||
if (this.minHeight) {
|
||||
style.minHeight = `${this.minHeight}px`;
|
||||
style.minHeight = `${this.minHeight}px`
|
||||
}
|
||||
if (this.height) {
|
||||
style.height = `${this.height}px`;
|
||||
style.height = `${this.height + 50}px`
|
||||
}
|
||||
return style;
|
||||
},
|
||||
return style
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: function (value) {
|
||||
value: function(value) {
|
||||
if (value !== this.editor.txt.html()) {
|
||||
this.editor.txt.html(this.value)
|
||||
}
|
||||
}
|
||||
// value为编辑框输入的内容,这里我监听了一下值,当父组件调用得时候,如果给value赋值了,子组件将会显示父组件赋给的值
|
||||
},
|
||||
data () {
|
||||
data() {
|
||||
return {
|
||||
|
||||
code: null,
|
||||
codeShow: false,
|
||||
// 默认有这么多菜单,meanArray有值以meanArray为准
|
||||
defaultMeanus: [
|
||||
'head',
|
||||
@@ -86,17 +109,90 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
|
||||
|
||||
|
||||
pack(s){
|
||||
s = s.replace(/\/\*(.|\n)*?\*\//g, "");
|
||||
s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");
|
||||
s = s.replace(/\,[\s\.\#\d]*\{/g, "{");
|
||||
s = s.replace(/;\s*;/g, ";");
|
||||
s = s.replace(/;\s*}/g, "}");
|
||||
s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/);
|
||||
return (s == null) ? "" : s[1];
|
||||
},
|
||||
|
||||
openCode() {
|
||||
this.code = null
|
||||
this.code = htmlFormat(this.value)
|
||||
// this.code = this.value.replace(/</g, "<").replace(/>/g, ">").replace(/ /g, " ")
|
||||
// console.log(this.code,"this.code)")
|
||||
// let text = this.editor.txt.text().replace(/</ig, "<").replace(/>/ig, ">").replace(/ /ig, " ")
|
||||
// console.log(text,"text")
|
||||
this.codeShow = true
|
||||
},
|
||||
codeSuccess(){
|
||||
console.log(this.code)
|
||||
|
||||
|
||||
// let packer = new Packer;
|
||||
// let output = packer.pack(this.value, 0, 0);
|
||||
// console.log(output, "output")
|
||||
// let output= packageFormat(this.code)
|
||||
// this.setHtml(output)
|
||||
// this.editor.dangerouslyInsertHtml(this.code)
|
||||
this.code = null
|
||||
this.codeShow = false
|
||||
},
|
||||
init() {
|
||||
const _this = this
|
||||
this.editor = new Editor(this.$refs.editor)
|
||||
this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
|
||||
this.editor.config.uploadImgAccept = ['doc', 'docx', 'png', 'img', 'gif', 'bmp', 'webp']
|
||||
// this.editor.config.uploadImgShowBase64 = true // 使用 base64 保存图片
|
||||
// this.editor.config.uploadImgServer = process.env.VUE_APP_BASE_API + "/web/images"
|
||||
// this.editor.config.uploadFileName = "file"
|
||||
// this.editor.config.uploadImgParams= {
|
||||
//
|
||||
// }
|
||||
|
||||
this.editor.config.customUploadImg = function (resultFiles, insertImgFn) {
|
||||
// resultFiles 是 input 中选中的文件列表
|
||||
// insertImgFn 是获取图片 url 后,插入到编辑器的方法
|
||||
let forms = new FormData()
|
||||
let configs = {
|
||||
headers:{
|
||||
'Content-Type':'multipart/form-data',
|
||||
Authorization: getToken()
|
||||
}
|
||||
};
|
||||
forms.append('file',resultFiles[0])
|
||||
|
||||
axios.post(
|
||||
process.env.VUE_APP_BASE_API + "/sist/article/images",
|
||||
forms ,configs).then(res=>{
|
||||
console.log(res)
|
||||
let img = "<p></p><img src='"+res.data.data.href+"' alt='"+res.data.data.url+"'></p>"
|
||||
_this.setHtml(_this.getHtml() + img)
|
||||
})
|
||||
// 上传图片,返回结果,将图片插入到编辑器中
|
||||
}
|
||||
this.editor.config.height = this.height
|
||||
this.editor.config.pasteFilterStyle = false
|
||||
this.editor.config.zIndex = 10
|
||||
// this.editor.config.uploadImgHooks = {
|
||||
// customInsert: function (insertImg, result, editor2) {
|
||||
// // uploadResult(result);
|
||||
// console.log(result)
|
||||
// insertImg(result.data.url);
|
||||
// }
|
||||
// }
|
||||
this.setMenus() // 设置菜单
|
||||
this.editor.config.onchange = (html) => {
|
||||
_this.$emit('change', html) // 将内容同步到父组件中
|
||||
}
|
||||
this.editor.create() // 创建编辑器
|
||||
},
|
||||
setMenus () {
|
||||
setMenus() {
|
||||
// 设置菜单
|
||||
if (this.meanArray) {
|
||||
this.editor.config.menus = this.meanArray
|
||||
@@ -104,18 +200,20 @@ export default {
|
||||
this.editor.config.menus = this.defaultMeanus
|
||||
}
|
||||
},
|
||||
getHtml () {
|
||||
getHtml() {
|
||||
// 得到文本内容
|
||||
return this.editor.txt.html()
|
||||
},
|
||||
setHtml (txt) {
|
||||
setHtml(txt) {
|
||||
// 设置富文本里面的值
|
||||
this.editor.txt.html(txt)
|
||||
// this.editor.txt.html(txt)
|
||||
this.editor.txt.text(txt)
|
||||
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
mounted() {
|
||||
const that = this
|
||||
that.$nextTick(function () {
|
||||
that.$nextTick(function() {
|
||||
that.init()
|
||||
})
|
||||
}
|
||||
@@ -123,9 +221,20 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.editor{
|
||||
z-index: 1!important;
|
||||
white-space: pre-wrap!important;
|
||||
|
||||
.editor {
|
||||
z-index: 1 !important;
|
||||
white-space: pre-wrap !important;
|
||||
line-height: normal !important;
|
||||
}
|
||||
|
||||
.code {
|
||||
margin-top: 3rem;
|
||||
|
||||
}
|
||||
.textarea{
|
||||
width: 1036px;
|
||||
height: 750px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
223
ebts-ui/src/views/utils/tinymce/Tinymce.vue
Normal file
223
ebts-ui/src/views/utils/tinymce/Tinymce.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div class="tinymce-editor">
|
||||
<editor v-model="myValue"
|
||||
:init="init"
|
||||
>
|
||||
</editor>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import tinymce from 'tinymce/tinymce'
|
||||
import Editor from '@tinymce/tinymce-vue'
|
||||
import 'tinymce/themes/silver'
|
||||
// 编辑器插件plugins
|
||||
// 更多插件参考:https://www.tiny.cloud/docs/plugins/
|
||||
import 'tinymce/plugins/link' // 链接
|
||||
import 'tinymce/plugins/code' // 代码
|
||||
import 'tinymce/plugins/table' // 表单
|
||||
import 'tinymce/plugins/lists'
|
||||
import 'tinymce/plugins/contextmenu'
|
||||
import 'tinymce/plugins/wordcount'
|
||||
import 'tinymce/plugins/paste' // 张贴
|
||||
import 'tinymce/plugins/autosave' // 自动保存
|
||||
import 'tinymce/plugins/imagetools' // 图片
|
||||
// Any plugins you want to use has to be imported
|
||||
import 'tinymce/plugins/advlist'
|
||||
import 'tinymce/plugins/autolink'
|
||||
import 'tinymce/plugins/charmap'
|
||||
import 'tinymce/plugins/codesample'
|
||||
import 'tinymce/plugins/emoticons'
|
||||
import 'tinymce/plugins/fullscreen'
|
||||
import 'tinymce/plugins/hr'
|
||||
import 'tinymce/plugins/insertdatetime'
|
||||
import 'tinymce/plugins/media'
|
||||
import 'tinymce/plugins/noneditable'
|
||||
import 'tinymce/plugins/print'
|
||||
import 'tinymce/plugins/searchreplace'
|
||||
import 'tinymce/plugins/tabfocus'
|
||||
import 'tinymce/plugins/template'
|
||||
import 'tinymce/plugins/textpattern'
|
||||
import 'tinymce/plugins/visualblocks'
|
||||
import 'tinymce/plugins/anchor'
|
||||
import 'tinymce/plugins/autoresize'
|
||||
import 'tinymce/plugins/bbcode'
|
||||
import 'tinymce/plugins/colorpicker'
|
||||
import 'tinymce/plugins/directionality'
|
||||
import 'tinymce/plugins/fullpage'
|
||||
import 'tinymce/plugins/help'
|
||||
import 'tinymce/plugins/image'
|
||||
import 'tinymce/plugins/importcss'
|
||||
import 'tinymce/plugins/legacyoutput'
|
||||
import 'tinymce/plugins/nonbreaking'
|
||||
import 'tinymce/plugins/pagebreak'
|
||||
import 'tinymce/plugins/preview'
|
||||
import 'tinymce/plugins/save'
|
||||
import 'tinymce/plugins/spellchecker'
|
||||
import 'tinymce/plugins/textcolor'
|
||||
import 'tinymce/plugins/toc'
|
||||
import 'tinymce/plugins/visualchars'
|
||||
|
||||
// 自定义插件
|
||||
import './plugin/letterspacing/plugin' // 字间距
|
||||
import './plugin/indent/plugin' // 字间距
|
||||
import './plugin/lineheight/plugin'
|
||||
import { getToken } from '../../../utils/auth'
|
||||
import axios from 'axios' // 行高
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Editor
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
inline: {
|
||||
type: Boolean
|
||||
},
|
||||
/* 高度 */
|
||||
height: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
// 基本路径,默认为空根目录,如果你的项目发布后的地址为目录形式,
|
||||
// 即abc.com/tinymce,baseUrl需要配置成tinymce,不然发布后资源会找不到
|
||||
baseUrl: {
|
||||
type: String,
|
||||
default: '/admin/tinymce'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
plugins: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [
|
||||
'link table wordcount autosave imagetools paste letterspacing indent lineheight',
|
||||
'advlist autolink link image lists charmap print hr anchor pagebreak',
|
||||
'searchreplace visualblocks visualchars code fullscreen media nonbreaking',
|
||||
'table directionality emoticons textcolor paste textcolor colorpicker textpattern'
|
||||
]
|
||||
}
|
||||
},
|
||||
toolbar: {
|
||||
type: String,
|
||||
default: `undo redo | fontsizeselect bold italic underline strikethrough | forecolor backcolor | alignleft aligncenter alignright alignjustify |
|
||||
| uploadimg image | table lineheight pastetext removeformat | customBtn letterspacing indent lineheight`
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
init: {
|
||||
language_url: `/admin/tinymce/langs/zh_CN.js`,
|
||||
language: 'zh_CN',
|
||||
skin_url: `/admin/tinymce/skins/ui/oxide`,
|
||||
content_css: `/admin/tinymce/skins/content/default/content.css`,
|
||||
base_url: this.baseUrl,
|
||||
height: 800,
|
||||
plugins: this.plugins,
|
||||
toolbar: this.toolbar,
|
||||
branding: false,
|
||||
selector: 'textarea',
|
||||
// menubar: false,
|
||||
fontsize_formats: '11px 12px 14px 16px 18px 24px 36px 48px 50px 56px 60px 64px',
|
||||
// 自定义字间距
|
||||
letterspacing_val: '1px 2px 3px 4px 5px',
|
||||
paste_data_images: true,
|
||||
// setup: (editor) => {
|
||||
// // 自定义新的工具栏按钮
|
||||
// editor.ui.registry.addButton('customBtn', {
|
||||
// tooltip: '新的工具栏按钮',
|
||||
// text: '新的工具栏按钮',
|
||||
// onAction: () => {
|
||||
// window.alert('新的工具栏按钮')
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
// 此处为图片上传处理函数,这个直接用了base64的图片形式上传图片,
|
||||
// 如需ajax上传可参考https://www.tiny.cloud/docs/configure/file-image-upload/#images_upload_handler
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
// images_upload_handler: (blobInfo, success, failure) => {
|
||||
//
|
||||
//
|
||||
// const img = 'data:image/jpeg;base64,' + blobInfo.base64()
|
||||
// success(img)
|
||||
// },
|
||||
images_upload_handler: (blobInfo, success, failure) => {
|
||||
// const img = 'data:image/jpeg;base64,' + blobInfo.base64()
|
||||
// success(img)
|
||||
|
||||
let formData = new FormData()
|
||||
formData.append('file', blobInfo.blob())
|
||||
console.log(formData, blobInfo.blob())
|
||||
let configs = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
axios.post(
|
||||
process.env.VUE_APP_BASE_API + '/sist/article/images',
|
||||
formData, configs).then(res => {
|
||||
console.log(res)
|
||||
success(res.data.data.href)
|
||||
})
|
||||
}
|
||||
},
|
||||
myValue: this.value,
|
||||
isShowFileDlg: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
tinymce.init({
|
||||
|
||||
images_upload_handler: (blobInfo, success, failure) => {
|
||||
this.upload_handler(blobInfo, success, failure)
|
||||
}
|
||||
|
||||
})
|
||||
},
|
||||
// created() {
|
||||
// tinymce.init({})
|
||||
// },
|
||||
methods: {
|
||||
|
||||
upload_handler(blobInfo, success, failure) {
|
||||
console.log('我被触发了')
|
||||
console.log(blobInfo, 'blobInfo')
|
||||
console.log(success, 'success')
|
||||
console.log(failure, 'failure')
|
||||
console.log(progress, 'progress')
|
||||
const img = 'data:image/jpeg;base64,' + blobInfo.base64()
|
||||
success(img)
|
||||
let forms = new FormData()
|
||||
let configs = {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: getToken()
|
||||
}
|
||||
}
|
||||
forms.append('file', blobInfo.blob())
|
||||
|
||||
axios.post(
|
||||
process.env.VUE_APP_BASE_API + '/sist/article/images',
|
||||
forms, configs).then(res => {
|
||||
console.log(res)
|
||||
|
||||
})
|
||||
console.log(forms, 'forms')
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
value(newValue) {
|
||||
this.myValue = newValue
|
||||
},
|
||||
myValue(newValue) {
|
||||
this.$emit('input', newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
47
ebts-ui/src/views/utils/tinymce/plugin/indent/plugin.js
Normal file
47
ebts-ui/src/views/utils/tinymce/plugin/indent/plugin.js
Normal file
@@ -0,0 +1,47 @@
|
||||
tinymce.PluginManager.add('indent2em', function(editor, url) {
|
||||
var pluginName='首行缩进';
|
||||
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
|
||||
var indent2em_val = editor.getParam('indent2em_val', '2em');
|
||||
var doAct = function () {
|
||||
var dom = editor.dom;
|
||||
var blocks = editor.selection.getSelectedBlocks();
|
||||
var act = '';
|
||||
global$1.each(blocks, function (block) {
|
||||
if(act==''){
|
||||
act = dom.getStyle(block,'text-indent')==indent2em_val ? 'remove' : 'add';
|
||||
}
|
||||
if( act=='add' ){
|
||||
dom.setStyle(block, 'text-indent', indent2em_val);
|
||||
}else{
|
||||
var style=dom.getAttrib(block,'style');
|
||||
style = style.replace(/text-indent:[\s]*2em;/ig,'');
|
||||
dom.setAttrib(block,'style',style);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
editor.ui.registry.addButton('indent2em', {
|
||||
text: '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M170.666667 563.2v-102.4H887.466667v102.4zM170.666667 836.266667v-102.4H887.466667v102.4zM512 290.133333v-102.4H887.466667v102.4zM238.933333 341.333333V136.533333l204.8 102.4z" fill="#2c2c2c" p-id="5210"></path></svg>',
|
||||
tooltip: pluginName,
|
||||
onAction: function () {
|
||||
doAct();
|
||||
}
|
||||
});
|
||||
|
||||
editor.ui.registry.addMenuItem('indent2em', {
|
||||
text: pluginName,
|
||||
onAction: function() {
|
||||
doAct();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php",
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
47
ebts-ui/src/views/utils/tinymce/plugin/indent/plugin.min.js
vendored
Normal file
47
ebts-ui/src/views/utils/tinymce/plugin/indent/plugin.min.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
tinymce.PluginManager.add('indent2em', function(editor, url) {
|
||||
var pluginName='首行缩进';
|
||||
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
|
||||
var indent2em_val = editor.getParam('indent2em_val', '2em');
|
||||
var doAct = function () {
|
||||
var dom = editor.dom;
|
||||
var blocks = editor.selection.getSelectedBlocks();
|
||||
var act = '';
|
||||
global$1.each(blocks, function (block) {
|
||||
if(act==''){
|
||||
act = dom.getStyle(block,'text-indent')==indent2em_val ? 'remove' : 'add';
|
||||
}
|
||||
if( act=='add' ){
|
||||
dom.setStyle(block, 'text-indent', indent2em_val);
|
||||
}else{
|
||||
var style=dom.getAttrib(block,'style');
|
||||
style = style.replace(/text-indent:[\s]*2em;/ig,'');
|
||||
dom.setAttrib(block,'style',style);
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
editor.ui.registry.addButton('indent2em', {
|
||||
text: '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M170.666667 563.2v-102.4H887.466667v102.4zM170.666667 836.266667v-102.4H887.466667v102.4zM512 290.133333v-102.4H887.466667v102.4zM238.933333 341.333333V136.533333l204.8 102.4z" fill="#2c2c2c" p-id="5210"></path></svg>',
|
||||
tooltip: pluginName,
|
||||
onAction: function () {
|
||||
doAct();
|
||||
}
|
||||
});
|
||||
|
||||
editor.ui.registry.addMenuItem('indent2em', {
|
||||
text: pluginName,
|
||||
onAction: function() {
|
||||
doAct();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: "http://tinymce.ax-z.cn/more-plugins/indent2em.php",
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
tinymce.PluginManager.add('letterspacing', function (editor, url) {
|
||||
var pluginName = '字间距'
|
||||
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools')
|
||||
var letterspacing_val = editor.getParam('letterspacing_val', '1px 2px 3px 4px 5px')
|
||||
|
||||
editor.on('init', function () {
|
||||
editor.formatter.register({
|
||||
letterspacing: {inline: 'span', styles: {'letter-spacing': '%value'}}
|
||||
})
|
||||
})
|
||||
|
||||
var doAct = function (value) {
|
||||
editor.formatter.apply('letterspacing', {value: value})
|
||||
editor.fire('change', {})
|
||||
}
|
||||
|
||||
editor.ui.registry.addMenuButton('letterspacing', {
|
||||
text: '<svg t="1570979572631" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12244" width="20" height="20" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M33.450667 3.413333h102.4v956.8256H33.450667V3.413333z m887.330133 1.8432h102.4v957.713067h-102.4V5.188267z m-425.301333 200.704h108.9536l223.6416 584.977067h-102.4l-53.248-146.6368H427.485867l-53.248 146.6368h-102.4l223.6416-584.9088z m-39.3216 359.697067H643.754667L552.004267 309.248h-3.2768L456.157867 565.6576z" fill="#2c2c2c" p-id="12245"></path></svg>',
|
||||
tooltip: pluginName,
|
||||
fetch: function (callback) {
|
||||
var dom = editor.dom
|
||||
var blocks = editor.selection.getSelectedBlocks()
|
||||
var lhv = 0
|
||||
global$1.each(blocks, function (block) {
|
||||
if (lhv == 0) {
|
||||
lhv = dom.getStyle(block, 'letterspacing') ? dom.getStyle(block, 'letterspacing') : 0
|
||||
}
|
||||
})
|
||||
|
||||
var items = letterspacing_val.split(' ').map(function (item) {
|
||||
var text = item
|
||||
var value = item
|
||||
return {
|
||||
type: 'togglemenuitem',
|
||||
text: text,
|
||||
active: lhv == value ? true : false,
|
||||
onAction: function () {
|
||||
doAct(value)
|
||||
}
|
||||
}
|
||||
})
|
||||
callback(items)
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: 'http://tinymce.ax-z.cn/more-plugins/lineheight.php',
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
57
ebts-ui/src/views/utils/tinymce/plugin/lineheight/plugin.js
Normal file
57
ebts-ui/src/views/utils/tinymce/plugin/lineheight/plugin.js
Normal file
@@ -0,0 +1,57 @@
|
||||
tinymce.PluginManager.add('lineheight', function(editor, url) {
|
||||
var pluginName='设置行高';
|
||||
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
|
||||
var lineheight_val = editor.getParam('lineheight_val', '1 1.5 1.6 1.75 1.8 2 3 4 5');
|
||||
|
||||
editor.on('init', function() {
|
||||
editor.formatter.register({
|
||||
lineheight: {
|
||||
selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table',
|
||||
styles: { 'line-height': '%value' }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var doAct = function (value) {
|
||||
editor.formatter.apply('lineheight', { value: value });
|
||||
editor.fire('change', {});
|
||||
};
|
||||
|
||||
editor.ui.registry.addMenuButton('lineheight', {
|
||||
text: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.984 12.984v-1.969h12v1.969h-12zM9.984 18.984v-1.969h12v1.969h-12zM9.984 5.016h12v1.969h-12v-1.969zM6 6.984v10.031h2.484l-3.469 3.469-3.516-3.469h2.484v-10.031h-2.484l3.516-3.469 3.469 3.469h-2.484z"></path></svg>',
|
||||
tooltip: pluginName,
|
||||
fetch: function(callback) {
|
||||
var dom = editor.dom;
|
||||
var blocks = editor.selection.getSelectedBlocks();
|
||||
var lhv = 0;
|
||||
global$1.each(blocks, function(block) {
|
||||
if(lhv==0){
|
||||
lhv = dom.getStyle(block,'line-height') ? dom.getStyle(block,'line-height') : 0;
|
||||
}
|
||||
});
|
||||
|
||||
var items = lineheight_val.split(' ').map(function(item){
|
||||
var text = item;
|
||||
var value = item;
|
||||
return {
|
||||
type: 'togglemenuitem',
|
||||
text: text,
|
||||
active : lhv==value ? true :false,
|
||||
onAction: function() {
|
||||
doAct(value);
|
||||
}
|
||||
};
|
||||
});
|
||||
callback(items);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: "http://tinymce.ax-z.cn/more-plugins/lineheight.php",
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
57
ebts-ui/src/views/utils/tinymce/plugin/lineheight/plugin.min.js
vendored
Normal file
57
ebts-ui/src/views/utils/tinymce/plugin/lineheight/plugin.min.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
tinymce.PluginManager.add('lineheight', function(editor, url) {
|
||||
var pluginName='设置行高';
|
||||
var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools');
|
||||
var lineheight_val = editor.getParam('lineheight_val', '1 1.5 1.6 1.75 1.8 2 3 4 5');
|
||||
|
||||
editor.on('init', function() {
|
||||
editor.formatter.register({
|
||||
lineheight: {
|
||||
selector: 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table',
|
||||
styles: { 'line-height': '%value' }
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var doAct = function (value) {
|
||||
editor.formatter.apply('lineheight', { value: value });
|
||||
editor.fire('change', {});
|
||||
};
|
||||
|
||||
editor.ui.registry.addMenuButton('lineheight', {
|
||||
text: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M9.984 12.984v-1.969h12v1.969h-12zM9.984 18.984v-1.969h12v1.969h-12zM9.984 5.016h12v1.969h-12v-1.969zM6 6.984v10.031h2.484l-3.469 3.469-3.516-3.469h2.484v-10.031h-2.484l3.516-3.469 3.469 3.469h-2.484z"></path></svg>',
|
||||
tooltip: pluginName,
|
||||
fetch: function(callback) {
|
||||
var dom = editor.dom;
|
||||
var blocks = editor.selection.getSelectedBlocks();
|
||||
var lhv = 0;
|
||||
global$1.each(blocks, function(block) {
|
||||
if(lhv==0){
|
||||
lhv = dom.getStyle(block,'line-height') ? dom.getStyle(block,'line-height') : 0;
|
||||
}
|
||||
});
|
||||
|
||||
var items = lineheight_val.split(' ').map(function(item){
|
||||
var text = item;
|
||||
var value = item;
|
||||
return {
|
||||
type: 'togglemenuitem',
|
||||
text: text,
|
||||
active : lhv==value ? true :false,
|
||||
onAction: function() {
|
||||
doAct(value);
|
||||
}
|
||||
};
|
||||
});
|
||||
callback(items);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: pluginName,
|
||||
url: "http://tinymce.ax-z.cn/more-plugins/lineheight.php",
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user