mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2025-12-18 17:05:54 +08:00
feat: ✨ 商家端富文本改为本地引入
This commit is contained in:
130
seller/src/views/lili-components/editor/index.vue
Normal file
130
seller/src/views/lili-components/editor/index.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<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 "@/views/lili-components/editor/config";
|
||||
|
||||
import uploadImage from "@/views/lili-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>
|
||||
211
seller/src/views/lili-components/editor/upload-image.vue
Normal file
211
seller/src/views/lili-components/editor/upload-image.vue
Normal file
@@ -0,0 +1,211 @@
|
||||
<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(item)"
|
||||
></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="(list)=>{ selectedImage = list}" @callback="handleCallback" />
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import vuedraggable from "vuedraggable";
|
||||
import {uploadFile} from "@/libs/axios";
|
||||
import OssManage from "@/views/sys/oss-manage/ossManage";
|
||||
|
||||
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: {
|
||||
handleClickUploadImage(){
|
||||
this.show = true
|
||||
},
|
||||
// 回调给父级
|
||||
callback() {
|
||||
// 先给数据做一下处理 然后将数据传给父级
|
||||
const formatImages = this.images.map((item) => item.url);
|
||||
this.$emit('callback',formatImages)
|
||||
},
|
||||
// 移除商品图片
|
||||
handleRemoveGoodsPicture(file) {
|
||||
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.$Message.success("导入成功")
|
||||
this.images.push({url:val.url})
|
||||
},
|
||||
// 从资源库中导入图片
|
||||
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>
|
||||
Reference in New Issue
Block a user