312 lines
6.9 KiB
Vue
312 lines
6.9 KiB
Vue
<script setup>
|
|
import {
|
|
ref,
|
|
reactive,
|
|
onMounted,
|
|
onUnmounted,
|
|
getCurrentInstance,
|
|
defineProps,
|
|
defineEmits,
|
|
defineExpose,
|
|
} from 'vue'
|
|
// 工具库
|
|
import util from '@/common/js/util'
|
|
// 调色板
|
|
import pickerColor from '@/components/public/pickerColor/pickerColor.vue'
|
|
|
|
const {
|
|
proxy
|
|
} = getCurrentInstance()
|
|
const props = defineProps({
|
|
modelValue: String
|
|
})
|
|
//
|
|
const emit = defineEmits(['update:modelValue']);
|
|
// 编辑器内容
|
|
const formats = reactive({})
|
|
// 编辑器上下文对象
|
|
const editorCtx = ref(null)
|
|
// 设置颜色板
|
|
const color = reactive({
|
|
// 前景色
|
|
forecolor: '#ff0000',
|
|
// 背景色
|
|
backgroundColor: '#ff0000',
|
|
})
|
|
// 颜色板键值
|
|
const colorKey = ref('forecolor')
|
|
// 富文本编辑器宽度
|
|
const editorWidth = ref(0)
|
|
|
|
onMounted(() => {
|
|
// 创建编辑器上下文对象
|
|
onEditorReady()
|
|
// 获取编辑器节点信息
|
|
getEditorInfo()
|
|
})
|
|
|
|
// 创建编辑器上下文对象
|
|
function onEditorReady() {
|
|
uni.createSelectorQuery().select('#editor').context((res) => {
|
|
editorCtx.value = res.context
|
|
}).exec()
|
|
}
|
|
|
|
// 获取编辑器节点信息 用来处理图片
|
|
function getEditorInfo() {
|
|
const query = uni.createSelectorQuery().in(proxy);
|
|
query.select("#editor").boundingClientRect((data) => {
|
|
editorWidth.value = data.width
|
|
}).exec();
|
|
}
|
|
|
|
// 初始化编辑器上下文对象
|
|
function init(html) {
|
|
editorCtx.value.setContents({
|
|
html,
|
|
})
|
|
}
|
|
|
|
// 撤销
|
|
function undo() {
|
|
editorCtx.value.undo()
|
|
}
|
|
|
|
// 重做
|
|
function redo() {
|
|
editorCtx.value.redo()
|
|
}
|
|
|
|
/**
|
|
* 执行editor方法
|
|
* @param {Object} event
|
|
*/
|
|
function handleEditor(event) {
|
|
let {
|
|
name,
|
|
value
|
|
} = event.target.dataset
|
|
if (!name) return
|
|
editorCtx.value.format(name, value)
|
|
}
|
|
|
|
/**
|
|
* 编辑器状态被变化
|
|
* @param {Object} e
|
|
*/
|
|
function onStatusChange(e) {
|
|
Object.assign(formats, e.detail)
|
|
}
|
|
|
|
// 插入下划线
|
|
function handleInsertDivider() {
|
|
editorCtx.value.insertDivider()
|
|
}
|
|
|
|
// 清空编辑器内容
|
|
function handleClear() {
|
|
editorCtx.value.clear()
|
|
}
|
|
|
|
// 清除所有格式
|
|
function handleRemoveFormat() {
|
|
editorCtx.value.removeFormat()
|
|
}
|
|
|
|
// 插入图片
|
|
function handleImage() {
|
|
util.upload_image({
|
|
type: 1,
|
|
success: rs => {
|
|
editorCtx.value.insertImage({
|
|
src: rs.value,
|
|
alt: '图像',
|
|
width: Math.min(rs.width, editorWidth.value),
|
|
extClass: 'editorImg',
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 选择颜色
|
|
* @param {Object} key 需要修改颜色的键
|
|
*/
|
|
function handleColor(key) {
|
|
colorKey.value = key
|
|
|
|
proxy.$refs.pickerColorRef.open()
|
|
}
|
|
|
|
/**
|
|
* 选择颜色
|
|
* @param {Object} event
|
|
*/
|
|
function handlePickerColorConfirm(event) {
|
|
// console.log('event', event)
|
|
color[colorKey.value] = event
|
|
}
|
|
|
|
// 设置标题
|
|
function handleHeader() {
|
|
const config = [{
|
|
name: '一级标题',
|
|
value: '1'
|
|
},
|
|
{
|
|
name: '二级标题',
|
|
value: '2'
|
|
},
|
|
{
|
|
name: '三级标题',
|
|
value: '3'
|
|
},
|
|
{
|
|
name: '四级标题',
|
|
value: '4'
|
|
},
|
|
{
|
|
name: '五级标题',
|
|
value: '5'
|
|
},
|
|
{
|
|
name: '六级标题',
|
|
value: '6'
|
|
}
|
|
]
|
|
|
|
// 多选菜单
|
|
uni.showActionSheet({
|
|
itemList: config.map(item => item.name),
|
|
success: (res) => {
|
|
editorCtx.value.format('header', config[res.tapIndex].value)
|
|
}
|
|
})
|
|
}
|
|
|
|
// 富文本编辑
|
|
function handleEditorInput(event) {
|
|
emit('update:modelValue', event.detail.html)
|
|
}
|
|
|
|
defineExpose({
|
|
init,
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<view class="container ptb30">
|
|
<view class='toolbar' @click="handleEditor">
|
|
<!-- 加粗 -->
|
|
<view class="item" data-name="bold">加粗</view>
|
|
<!-- 倾斜 -->
|
|
<!-- <view class="item" data-name="italic">倾斜</view> -->
|
|
<!-- 下划线 -->
|
|
<view class="item" data-name="underline">下划线</view>
|
|
<!-- 删除线 -->
|
|
<view class="item" data-name="strike">删除线</view>
|
|
<!-- 左对齐 -->
|
|
<view class="item" data-name="align" data-value="left">左对齐</view>
|
|
<!-- 居中 -->
|
|
<view class="item" data-name="align" data-value="center">居中</view>
|
|
<!-- 右对齐 -->
|
|
<view class="item" data-name="align" data-value="right">右对齐</view>
|
|
<!-- 两端对齐 -->
|
|
<!-- <view class="item" data-name="align" data-value="justify">两端对齐</view> -->
|
|
<!-- 清除格式 -->
|
|
<view class="item" @tap="handleRemoveFormat">清除所有格式</view>
|
|
<!-- 字体颜色 -->
|
|
<view class="item df aic" data-name="color" :data-value="color.forecolor">
|
|
文本颜色
|
|
<view class="colorBox ml10" :style="{backgroundColor:color.forecolor}"
|
|
@click.stop="handleColor('forecolor')"></view>
|
|
</view>
|
|
<!-- 字体背景 -->
|
|
<view class="item df aic" data-name="backgroundColor" :data-value="color.backgroundColor">
|
|
文本背景
|
|
<view class="colorBox ml10" :style="{backgroundColor: color.backgroundColor}"
|
|
@click.stop="handleColor('backgroundColor')"></view>
|
|
</view>
|
|
<!-- 有序列表 -->
|
|
<view class="item" data-name="list" data-value="ordered">数字列表</view>
|
|
<!-- 点列表 -->
|
|
<view class="item" data-name="list" data-value="bullet">点列表</view>
|
|
<!-- 撤销 -->
|
|
<view class="item" @tap="undo">撤销</view>
|
|
<!-- 重做 -->
|
|
<view class="item" @tap="redo">重做</view>
|
|
<!-- 增加缩进 -->
|
|
<!-- <view class="item" data-name="indent" data-value="+1">增加缩进</view> -->
|
|
<!-- 减少缩进 -->
|
|
<!-- <view class="item" data-name="indent" data-value="-1">减少缩进</view> -->
|
|
<!-- 分割线 -->
|
|
<view class="item" @tap="handleInsertDivider">分割线</view>
|
|
<!-- 插入图片 -->
|
|
<view class="item" @tap="handleImage">插入图片</view>
|
|
<!-- 大标题 -->
|
|
<view class="item" @click.stop="handleHeader">插入标题</view>
|
|
<!-- 下标 -->
|
|
<!-- <view class="item" data-name="script" data-value="sub">下标</view> -->
|
|
<!-- 上标 -->
|
|
<!-- <view class="item" data-name="script" data-value="super">上标</view> -->
|
|
<!-- 清空 -->
|
|
<view class="item" @tap="handleClear">清空内容</view>
|
|
</view>
|
|
|
|
<!-- 内容 -->
|
|
<view class="main">
|
|
<editor id="editor" class="ql-container" placeholder="在此输入产品详情" showImgSize showImgToolbar showImgResize
|
|
@statuschange="onStatusChange" @ready="onEditorReady" @input="handleEditorInput">
|
|
</editor>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 调色板 -->
|
|
<pickerColor ref="pickerColorRef" @change="handlePickerColorConfirm" />
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
// 富文本编辑区
|
|
.container {
|
|
|
|
.toolbar {
|
|
box-sizing: border-box;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
// 列表项
|
|
.item {
|
|
margin: 0 20rpx 20rpx 0;
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
// 内容
|
|
.active {
|
|
color: #FF9B27;
|
|
}
|
|
|
|
// 内容
|
|
.main {
|
|
background: #fff;
|
|
}
|
|
|
|
// 色块
|
|
.colorBox {
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
}
|
|
}
|
|
|
|
// 富文本区
|
|
.ql-container {
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
height: 50vh;
|
|
padding: 10rpx;
|
|
font-size: 16px;
|
|
// background-color: #f4f4f4;
|
|
border-radius: 10rpx;
|
|
border: 2rpx solid #ccc;
|
|
}
|
|
</style> |