mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2025-12-17 16:35:53 +08:00
Merge branch 'master' of gitee.com:beijing_hongye_huicheng/lilishop-ui
This commit is contained in:
@@ -1,33 +1,25 @@
|
||||
import plugins from "./plugins";
|
||||
import toobar from "./toolbar";
|
||||
import { upLoadFile } from "@/api/common";
|
||||
|
||||
const localCDN = window.location.origin + "/tinymce"; //本地引入
|
||||
export const initEditor = {
|
||||
base_url: localCDN,
|
||||
height: "400px",
|
||||
language: "zh_CN",
|
||||
language: "zh-Hans",
|
||||
menubar: "file edit view format table", // 菜单:指定应该出现哪些菜单
|
||||
toolbar: toobar, // 分组工具栏控件
|
||||
plugins: plugins, // 插件(比如: advlist | link | image | preview等)
|
||||
plugins:plugins, // 插件(比如: advlist | link | image | preview等)
|
||||
object_resizing: false, // 是否禁用表格图片大小调整
|
||||
end_container_on_empty_block: true, // enter键 分块
|
||||
powerpaste_word_import: "merge", // 是否保留word粘贴样式 clean | merge
|
||||
advlist_bullet_styles: "square", // 无序列表 有序列表
|
||||
maxSize: "2097152", // 设置图片大小
|
||||
accept: "image/jpeg, image/png", // 设置图片上传规则
|
||||
images_upload_handler: async function (blobInfo, success, failure) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", blobInfo.blob());
|
||||
try {
|
||||
const res = await upLoadFile(formData);
|
||||
if (res.result) {
|
||||
success(res.result)
|
||||
} else {
|
||||
failure("上传文件有误请稍后重试");
|
||||
}
|
||||
} catch (e) {
|
||||
failure('上传出错')
|
||||
}
|
||||
},
|
||||
paste_data_images:false,
|
||||
browser_spellcheck: true, // 拼写检查
|
||||
branding: false, // 去水印
|
||||
elementpath: false, // 禁用编辑器底部的状态栏
|
||||
statusbar: false, // 隐藏编辑器底部的状态栏
|
||||
// init_instance_callback: function (editor) {
|
||||
// var freeTiny = document.querySelector(".tox .tox-notification--in .tox-notification .tox-notification--warning .tox .tox-notification--warning .tox-notifications-container");
|
||||
// freeTiny.style.display = "none";
|
||||
@@ -51,7 +43,4 @@ export const initEditor = {
|
||||
|
||||
ul,ol{ list-style-position:inside; }
|
||||
`, // 设置样式
|
||||
statusbar: false, // 隐藏编辑器底部的状态栏
|
||||
elementpath: false, // 禁用编辑器底部的状态栏
|
||||
paste_data_images: true, // 允许粘贴图像
|
||||
};
|
||||
|
||||
129
manager/src/components/editor/index.vue
Normal file
129
manager/src/components/editor/index.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 使用 fullscreen 类来控制是否全屏显示 -->
|
||||
<div :class="{ fullscreen: fullscreen }" class="tinymce-container">
|
||||
<!-- 使用 tinymce-textarea 类作为编辑器的文本区域 -->
|
||||
<uploadImage @callback="insertImage" />
|
||||
<textarea :id="tinymceId" class="tinymce-textarea" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { initEditor } from "@/components/editor/config";
|
||||
import uploadImage from "@/components/editor/upload-image.vue";
|
||||
export default {
|
||||
components:{uploadImage},
|
||||
name: "Tinymce",
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
height:{
|
||||
type:String,
|
||||
default:'500px'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 引入编辑器的配置
|
||||
initEditor,
|
||||
hasChange: false, // 标记内容是否有更改
|
||||
hasInit: false, // 标记编辑器是否已初始化
|
||||
tinymceId:
|
||||
"tinymce-" + +new Date() + ((Math.random() * 1000).toFixed(0) + ""), // 生成唯一的编辑器 ID
|
||||
fullscreen: false, // 标记编辑器是否处于全屏模式
|
||||
toolbar: [], // 工具栏配置
|
||||
content: "", // 编辑器内容
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
if (!this.hasChange && this.hasInit) {
|
||||
// 当内容有更改且编辑器已初始化时,更新编辑器的内容
|
||||
this.$nextTick(() =>
|
||||
window.tinymce.get(this.tinymceId).setContent(val || "")
|
||||
);
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 数据返回并给富文本框插入图片
|
||||
insertImage(arr){
|
||||
arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img src="${v}" >`))
|
||||
},
|
||||
init() {
|
||||
// 初始化编辑器
|
||||
this.initTinymce();
|
||||
},
|
||||
initTinymce() {
|
||||
const _this = this;
|
||||
window.tinymce.init({
|
||||
selector: `#${this.tinymceId}`,
|
||||
convert_urls: false,
|
||||
init_instance_callback: (editor) => {
|
||||
if (_this.value) {
|
||||
// 如果有初始值,则设置编辑器的内容为初始值
|
||||
this.$nextTick(() => editor.setContent(_this.value));
|
||||
}
|
||||
_this.hasInit = true;
|
||||
// 监听编辑器内容的变化
|
||||
editor.on("NodeChange Change KeyUp SetContent", (event) => {
|
||||
if (_this.value) {
|
||||
// 内容发生更改
|
||||
this.hasChange = true;
|
||||
}
|
||||
// 通过 input 事件将编辑器的内容传递给父组件
|
||||
this.$emit("input", editor.getContent());
|
||||
});
|
||||
},
|
||||
setup(editor) {
|
||||
// 监听全屏状态变化
|
||||
editor.on("FullscreenStateChanged", (e) => {
|
||||
_this.fullscreen = e.state;
|
||||
});
|
||||
},
|
||||
..._this.initEditor,
|
||||
|
||||
height:this.height
|
||||
});
|
||||
},
|
||||
setContent(value) {
|
||||
// 设置编辑器的内容
|
||||
window.tinymce.get(this.tinymceId).setContent(value);
|
||||
},
|
||||
getContent() {
|
||||
// 获取编辑器的内容
|
||||
return window.tinymce.get(this.tinymceId).getContent();
|
||||
},
|
||||
destroyTinymce() {
|
||||
const tinymce = window.tinymce.get(this.tinymceId);
|
||||
|
||||
if (tinymce) {
|
||||
// 销毁编辑器实例
|
||||
tinymce.destroy();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
activated() {
|
||||
if (window.tinymce) {
|
||||
this.initTinymce();
|
||||
}
|
||||
},
|
||||
deactivated() {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyTinymce();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -1,4 +1,4 @@
|
||||
const plugins = [
|
||||
'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount'
|
||||
'advlist', 'anchor', 'autolink', 'autosave', 'code', 'codesample', 'directionality', 'emoticons', 'fullscreen', 'image', 'importcss', 'insertdatetime', 'link', 'lists', 'media', 'nonbreaking', 'pagebreak', 'preview', 'save', 'searchreplace', 'table', 'template', 'visualblocks', 'visualchars', 'wordcount'
|
||||
]
|
||||
export default plugins
|
||||
|
||||
213
manager/src/components/editor/upload-image.vue
Normal file
213
manager/src/components/editor/upload-image.vue
Normal file
@@ -0,0 +1,213 @@
|
||||
<template>
|
||||
<div class="wrapper">
|
||||
<Button @click="handleClickUploadImage">上传图片</Button>
|
||||
<Modal v-model="show" width="850" @on-ok="callback" title="上传图片">
|
||||
<div class="import-oss" @click="importOSS">
|
||||
从资源库中导入
|
||||
</div>
|
||||
<div style="display: flex; flex-wrap: wrap">
|
||||
<vuedraggable
|
||||
:animation="200"
|
||||
:list="images"
|
||||
>
|
||||
<div
|
||||
v-for="(item, __index) in images"
|
||||
:key="__index"
|
||||
class="upload-list"
|
||||
>
|
||||
<template>
|
||||
<img alt="image" :src="item.url"/>
|
||||
<div class="upload-list-cover">
|
||||
<div>
|
||||
<Icon
|
||||
size="30"
|
||||
type="md-search"
|
||||
@click.native="$previewImage(item.url)"
|
||||
></Icon>
|
||||
<Icon
|
||||
size="30"
|
||||
type="md-trash"
|
||||
@click.native="handleRemoveGoodsPicture(__index)"
|
||||
></Icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</vuedraggable>
|
||||
<div class="upload-box">
|
||||
<Upload
|
||||
ref="upload"
|
||||
:action="uploadFileUrl"
|
||||
:format="['jpg', 'jpeg', 'png']"
|
||||
:headers="{ ...accessToken }"
|
||||
:max-size="10240"
|
||||
:on-exceeded-size="handleMaxSize"
|
||||
:on-format-error="handleFormatError"
|
||||
:on-success="handleSuccessGoodsPicture"
|
||||
:show-upload-list="false"
|
||||
multiple
|
||||
type="drag"
|
||||
>
|
||||
<div style="width: 148px; height: 148px; line-height: 148px">
|
||||
<Icon size="20" type="md-add"></Icon>
|
||||
</div>
|
||||
</Upload>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal width="1000" v-model="showOssManager" @on-ok="confirmUrls">
|
||||
<OssManage ref="ossManage" @selected="handleCallback" />
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import vuedraggable from "vuedraggable";
|
||||
import { uploadFile } from "@/libs/axios";
|
||||
import OssManage from "@/views/sys/oss-manage/ossManage.vue";
|
||||
|
||||
export default {
|
||||
name: "upload-image",
|
||||
components: {
|
||||
OssManage,
|
||||
vuedraggable,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false, // 是否显示弹窗
|
||||
uploadFileUrl: uploadFile, // 上传地址
|
||||
accessToken:"",
|
||||
showOssManager:false, // 是否显示oss管理弹窗
|
||||
images:[],
|
||||
selectedImage:[]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.accessToken = {
|
||||
accessToken: this.getStore("accessToken"),
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
confirmUrl(){
|
||||
|
||||
},
|
||||
handleClickUploadImage(){
|
||||
this.show = true
|
||||
},
|
||||
// 回调给父级
|
||||
callback() {
|
||||
// 先给数据做一下处理 然后将数据传给父级
|
||||
const formatImages = this.images.map((item) => item.url);
|
||||
this.$emit('callback',formatImages)
|
||||
},
|
||||
// 移除商品图片
|
||||
handleRemoveGoodsPicture(__index) {
|
||||
this.images.splice(__index, 1);
|
||||
},
|
||||
// 图片大小不正确
|
||||
handleMaxSize(file) {
|
||||
this.$Notice.warning({
|
||||
title: "超过文件大小限制",
|
||||
desc: "图片大小不能超过10MB",
|
||||
});
|
||||
},
|
||||
// 图片格式不正确
|
||||
handleFormatError(file) {
|
||||
this.$Notice.warning({
|
||||
title: "文件格式不正确",
|
||||
desc: "文件 " + file.name + " 的格式不正确",
|
||||
});
|
||||
},
|
||||
// sku图片上传成功
|
||||
handleSuccessGoodsPicture(res, file) {
|
||||
if (file.response) {
|
||||
file.url = file.response.result;
|
||||
this.images.push(file);
|
||||
}
|
||||
},
|
||||
confirmUrls(){
|
||||
this.selectedImage.length ? this.selectedImage.forEach(element => {
|
||||
this.images.push({ url: element.url })
|
||||
}):''
|
||||
this.showOssManager = false
|
||||
},
|
||||
handleCallback(val){
|
||||
this.selectedImage = val
|
||||
},
|
||||
// 从资源库中导入图片
|
||||
importOSS(){
|
||||
this.showOssManager = true
|
||||
this.$refs.ossManage.selectImage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.import-oss{
|
||||
margin-bottom: 10px;
|
||||
text-align: right;
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
.wrapper{
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.upload-list {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
text-align: center;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
margin-right: 4px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.upload-box{
|
||||
margin: 10px 0;
|
||||
|
||||
}
|
||||
|
||||
.upload-list img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.upload-list-cover {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.upload-list:hover .upload-list-cover {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.upload-list-cover div {
|
||||
margin-top: 50px;
|
||||
width: 100%;
|
||||
|
||||
>i {
|
||||
width: 50%;
|
||||
margin-top: 8px;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -111,12 +111,12 @@
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem class="form-item-view-el" label="文章内容" prop="content">
|
||||
<editor
|
||||
ref="editor"
|
||||
openXss
|
||||
v-model="form.content"
|
||||
:init="{ ...initEditor,height:'800px' }"
|
||||
></editor>
|
||||
<tinymec
|
||||
ref="editor"
|
||||
openXss
|
||||
v-model="form.content"
|
||||
v-if="modalVisible"
|
||||
></tinymec>
|
||||
</FormItem>
|
||||
<FormItem label="是否展示" prop="openStatus">
|
||||
<i-switch size="large" v-model="form.openStatus">
|
||||
@@ -146,12 +146,10 @@ import {
|
||||
seeArticle,
|
||||
updateArticleStatus,
|
||||
} from "@/api/pages";
|
||||
import Editor from "@tinymce/tinymce-vue";
|
||||
import { initEditor } from "@/components/editor/config";
|
||||
import tinymec from "@/components/editor/index.vue";
|
||||
export default {
|
||||
|
||||
components: {
|
||||
editor: Editor,
|
||||
tinymec: tinymec,
|
||||
},
|
||||
props: {
|
||||
selected: {
|
||||
@@ -161,7 +159,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
initEditor: initEditor,
|
||||
selectedIndex: 99999, // 已选下标
|
||||
loading: true, // 表单加载状态
|
||||
modalType: 0, // 添加或编辑标识
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
</FormItem>
|
||||
<FormItem class="form-item-view-el" label="文章内容" prop="content">
|
||||
|
||||
<editor
|
||||
ref="editor"
|
||||
openXss
|
||||
v-model="form.article.content"
|
||||
:init="{ ...initEditor,height:'800px' }"
|
||||
></editor>
|
||||
<editor
|
||||
ref="editor"
|
||||
openXss
|
||||
v-model="form.article.content"
|
||||
v-if="modalVisible"
|
||||
></editor>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<div slot="footer">
|
||||
@@ -40,12 +40,12 @@ import {
|
||||
updatePrivacy,
|
||||
getPrivacy,
|
||||
} from "@/api/pages";
|
||||
import Editor from "@tinymce/tinymce-vue";
|
||||
import { initEditor } from "@/components/editor/config";
|
||||
import tinymec from "@/components/editor/index.vue";
|
||||
|
||||
export default {
|
||||
name: "privacy",
|
||||
components: {
|
||||
editor: Editor,
|
||||
editor: tinymec,
|
||||
},
|
||||
props: {
|
||||
selected: {
|
||||
@@ -55,7 +55,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
initEditor,
|
||||
loading: false, // 表单加载状态
|
||||
modalVisible: false, // 添加或编辑显示
|
||||
treeDataDefault: [],
|
||||
|
||||
@@ -1144,6 +1144,7 @@ export default {
|
||||
size += item.fileSize * 1.0;
|
||||
});
|
||||
this.totalSize = ((size * 1.0) / (1024 * 1024)).toFixed(2) + " MB";
|
||||
this.$emit("selected", e)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
Reference in New Issue
Block a user