基于uniapp的editor富文本仿csdn的app端样式

​​​​​​​先上效果图,

demo代码:editor.vue

<template>
	<view>
		<editor id="editor" ref="editor" style="height: auto;" class="ql-container" showImgSize showImgToolbar
			showImgResize @statuschange="onStatusChange" :read-only="readOnly" @ready="onEditorReady"
			@input="editorInput" placeholder="请输入商品描述..."></editor>
		<view class="toolMenu" @touchend.prevent="tool">
			<text class="toolBtn iconfont icon-charutupian" data-name="tupian"
				:class="currentTool=='tupian' ? 'selected' : ''"></text>
			<text class="toolBtn iconfont icon-zitiyanse" data-name="wenzi"
				:class="currentTool=='wenzi' ? 'selected' : ''"></text>
			<text class="toolBtn iconfont icon-fuwenben" data-name="wenben"
				:class="currentTool=='wenben' ? 'selected' : ''"></text>
			<text class="toolBtn iconfont icon-editor-link" data-name="link"
				:class="currentTool=='link' ? 'selected' : ''"></text>
			<text class="toolBtn iconfont icon-shangyibu" data-name="undo"></text>
			<text class="toolBtn iconfont icon-xiayibu" data-name="redo"></text>
		</view>
		<view v-if="currentTool=='wenzi'" @touchend.prevent="format">

			<view class="formatTitle">文字格式</view>
			<view class="formatMenu">
				<view class="formatItem"> <text data-name="bold" :class="formats.bold ? 'selected' : ''"
						class=" formatBtn iconfont icon-zitijiacu"></text>
				</view>
				<view class="formatItem"><text data-name="italic" :class="formats.italic ? 'selected' : ''"
						class="formatBtn iconfont icon-zitixieti"></text></view>
				<view class="formatItem"><text data-name="underline" :class="formats.underline ? 'selected' : ''"
						class="formatBtn iconfont icon-zitixiahuaxian"></text></view>
				<view class="formatItem"><text data-name="strike" :class="formats.strike ? 'selected' : ''"
						class="formatBtn iconfont icon-zitishanchuxian"></text></view>
			</view>


			<view class="formatTitle">对齐方式</view>
			<view class="formatMenu">
				<view class="formatItem"><text data-name="align" data-value="left"
						:class="formats.align === 'left' ? 'selected' : ''"
						class="formatBtn iconfont icon-zuoduiqi"></text></view>
				<view class="formatItem"><text data-name="align" data-value="center"
						:class="formats.align === 'center' ? 'selected' : ''"
						class="formatBtn iconfont icon-juzhongduiqi"></text></view>
				<view class="formatItem"><text data-name="align" data-value="right"
						:class="formats.align === 'right' ? 'selected' : ''"
						class="formatBtn iconfont icon-youduiqi"></text></view>
				<view class="formatItem"><text data-name="align" data-value="justify"
						:class="formats.align === 'justify' ? 'selected' : ''"
						class="formatBtn iconfont icon-zuoyouduiqi"></text></view>
			</view>
		</view>
		<view v-if="currentTool=='wenben'" @touchend.prevent="format">
			<view class="formatBox">
				<view class="box1">
					<view class="formatTitle">标题</view>
					<view class="formatMenu">
						<view class="formatItem"> <text data-name="header" :data-value="1"
								:class="formats.header === 1 ? 'selected' : ''" class=" formatBtn ">H1</text>
						</view>
						<view class="formatItem"><text data-name="header" :data-value="2"
								:class="formats.header === 2 ? 'selected' : ''" class="formatBtn ">H2</text>
						</view>
						<view class="formatItem"><text data-name="header" :data-value="3"
								:class="formats.header === 3 ? 'selected' : ''" class="formatBtn ">H3</text>
						</view>

					</view>
				</view>
				<view class="box2">
					<view class="formatTitle">背景</view>
					<view class="formatMenu">
						<view class="formatItem"> <text data-name="backgroundColor" data-value="#dbdbdb"
								:class="formats.backgroundColor=== '#dbdbdb' ? 'selected' : ''"
								class=" formatBtn iconfont icon-zitibao"></text>
						</view>
					</view>
				</view>
			</view>

			<view class="formatBox">
				<view class="box1">
					<view class="formatTitle">排序</view>
					<view class="formatMenu">
						<view class="formatItem"><text data-name="list" data-value="ordered"
								:class="formats.list === 'ordered'  ? 'selected' : ''"
								class="iconBig formatBtn iconfont icon-youxupailie"></text></view>
						<view class="formatItem"><text data-name="list" data-value="bullet"
								:class="formats.list === 'bullet'  ? 'selected' : ''"
								class="iconBig formatBtn iconfont icon-wuxupailie"></text></view>

					</view>
				</view>
				<view class="box2">
					<view class="formatTitle">分割</view>
					<view class="formatMenu">
								<view class="formatItem"> <text data-name="divider" class="iconBig formatBtn iconfont icon-fengexian"
								 ></text>
						</view>
					</view>
				</view>
			</view>
		</view>
		<u-popup :show="linkShow" @close="linkShow=false">
			<view>
				<view class="topbar">
					<view class="left">取消</view>
					<view class="center">添加链接</view>
					<view :class="linkAdd?'linkAdd':''" class="right">添加</view>
				</view>
				<view class="inputBox">
					<u--input placeholder="请输入链接地址,分享你的见闻" :focus="true" @change="linkOnChange">
						<text slot="prefix" style="color: #909399" class="  iconfont icon-editor-link"></text>
					</u--input>
				</view>
				<view class="inputBox">
					<u--input placeholder="请输入链接描述(选填)" prefixIcon="edit-pen"
						prefixIconStyle="font-size: 22px;color: #909399">
					</u--input>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>


	export default {
		data() {
			return {
				readOnly: false,
				formats: {},
				editorCtx: '',
				currentTool: '',
				linkShow: false,
				linkAdd: false,
			}
		},
		onLoad() {
			uni.onKeyboardHeightChange(res => {
				console.log(res.height)
			})
		},
		onUnload() {
			uni.offKeyboardHeightChange()
		},
		methods: {
			readOnlyChange() {
				this.readOnly = !this.readOnly
			},
			//图文详情-富文本初始化
			onEditorReady() {
				uni.createSelectorQuery().select('#editor').context((res) => {
					this.editorCtx = res.context
				}).exec()

			},
			//图文详情-富文本编辑输入时事件
			editorInput(e) {
				this.Content = e.detail.text
				this.ContentHtml = e.detail.html
			},
			format(e) {
				let {
					name,
					value
				} = e.target.dataset
				if (!name) return
				console.log('format', name, value)
				if ("divider" == name) {
					this.editorCtx.insertDivider({
						success: function() {
							console.log('insert divider success')
						}
					})
				
				} else {
					this.editorCtx.format(name, value)
				}


			},
			tool(e) {
				let {
					name
				} = e.target.dataset
				if (!name) return
				this.currentTool = name;
				console.log('currentTool', name)
				if ("tupian" === name) {

				}
				if ("wenzi" === name) {
					uni.hideKeyboard()
				}
				if ("wenben" === name) {
					uni.hideKeyboard()
				}
				if ("link" === name) {
					this.linkShow = true
				}
				if ("undo" === name) {
					this.editorCtx.undo()
				}
				if ("redo" === name) {
					this.editorCtx.redo()
				}


			},
	
			onStatusChange(e) {
				const formats = e.detail
				this.formats = formats
			},
			linkOnChange(e) {
				console.log(e);
				this.linkAdd = !!e;
			}
		}
	}
</script>

<style lang="scss">
	@import url('//at.alicdn.com/t/c/font_3813365_m08rcwzvql.css');

	.toolMenu {
		border-top: 1px solid $border-color-light;
		display: flex;
		flex-direction: row;
		text-align: center;

		.toolBtn {
			flex: 1;
			padding: 16rpx;

		}

		.selected {
			color: $font-color-light;
		}

		.disabled {
			color: #ccc;
		}
	}

	.formatTitle {
		margin: 28rpx;
		color: $font-color-light;
	}

	.formatMenu {
		background-color: $border-color-light;
		display: flex;
		flex-direction: row;
		text-align: center;
		padding: 28rpx;

		.formatItem {
			flex: 1;

		}

		.formatBtn {
			padding: 20rpx;
		}

		.iconBig {
			font-size: 20px;
		}

		.selected {
			background-color: $font-color-disabled;
		}
	}

	.formatBox {
		display: flex;
		flex-direction: row;

		.box1 {
			flex: 1;
		}

		.box2 {
			margin-left: 32rpx;
		}
	}

	.topbar {
		margin: 16rpx;
		margin-bottom: 32rpx;
		display: flex;
		flex-direction: row;

		.left,
		.right {
			color: $font-color-disabled;
		}

		.center {
			flex: 1;
			text-align: center;
		}

		.linkAdd {
			color: #333;
		}
	}

	.inputBox {
		margin: 32rpx;
	}
</style>

 注:插入图片我使用的自定义插件,没有放在代码,插入后,记得获取editor的html进行替换成网络链接

				this.selectFiles.forEach((item, index) => {
					if (this.ContentHtml.includes(item)) { //存在此图片
						this.ContentHtml = this.ContentHtml.replace(this.selectFiles[index],
							this.$api.cos207 + index + ".jpg");
					}
				});

超链接因为editor没有提供,使用的是html后续插入替换,这里代码就不放了,大概思路是插入‘【超链接1】’的文本,然后提交的时候进行替换

猜你喜欢

转载自blog.csdn.net/csdn_zuirenxiao/article/details/128222484
今日推荐