<template>
	<div class="rich-editor">
		<div class="rich-editor__toolbar">
			<ButtonGroup size="small" class="rich-editor__toolbar-group">
				<Button
					v-for="btn in toolbarButtons"
					:key="btn.key"
					:title="btn.label"
					:icon="btn.icon"
					@click="handleToolbar(btn)"
				>
					{{ btn.label }}
				</Button>
			</ButtonGroup>
			<Button size="small" icon="ios-image" type="primary" class="rich-editor__upload" :loading="uploading"
				@click="triggerUpload">
				插入图片
			</Button>
			<input ref="fileInput" class="rich-editor__file" type="file" accept="image/*" @change="handleUpload">
		</div>
		<div ref="editor" class="rich-editor__content" :data-placeholder="placeholder" :style="{ minHeight: `${height}px` }"
			contenteditable
			@input="handleInput" @focus="saveSelection" @keyup="saveSelection" @mouseup="saveSelection" />
	</div>
</template>

<script>
import { upload } from '@/api'

export default {
	name: 'RichEditor',
	props: {
		// 富文本初始内容
		value: {
			type: String,
			default: '',
		},
		// 提示语，用于空状态展示
		placeholder: {
			type: String,
			default: '请输入内容',
		},
		// 文本区域高度
		height: {
			type: Number,
			default: 280,
		},
	},
	data() {
		return {
			innerHTML: this.value,
			currentRange: null,
			uploading: false,
			toolbarButtons: [{
					key: 'bold',
					icon: 'ios-bold',
					label: '加粗',
					command: 'bold',
				},
				{
					key: 'italic',
					icon: 'ios-italic',
					label: '斜体',
					command: 'italic',
				},
				{
					key: 'underline',
					icon: 'ios-underline',
					label: '下划线',
					command: 'underline',
				},
				// 段落排版按钮：左/中/右对齐与分割线，覆盖常用排版需求
				{
					key: 'align-left',
					icon: 'ios-arrow-back',
					label: '左对齐',
					command: 'justifyLeft',
				},
				{
					key: 'align-center',
					icon: 'ios-remove',
					label: '居中对齐',
					command: 'justifyCenter',
				},
				{
					key: 'align-right',
					icon: 'ios-arrow-forward',
					label: '右对齐',
					command: 'justifyRight',
				},
				{
					key: 'horizontal-rule',
					icon: 'md-more',
					label: '分割线',
					command: 'insertHorizontalRule',
				},
				{
					key: 'clear',
					icon: 'md-trash',
					label: '清空内容',
					action: 'clear',
				},
			],
		}
	},
	watch: {
		value(val) {
			if (val !== this.innerHTML) {
				this.innerHTML = val || ''
				this.setContent(this.innerHTML)
			}
		},
	},
	mounted() {
		this.setContent(this.innerHTML)
	},
	methods: {
		// 将外部内容同步到编辑器
		setContent(content) {
			if (this.$refs.editor) {
				this.$refs.editor.innerHTML = content || ''
			}
		},
		// 执行基础格式化命令
		execCommand(command) {
			this.focusEditor()
			document.execCommand(command, false, null)
			this.syncContent()
		},
		// 点击工具栏按钮时统一处理，支持命令或自定义方法
		handleToolbar(btn) {
			if (btn.action === 'clear') {
				this.clearContent()
				return
			}
			if (btn.command) {
				this.execCommand(btn.command)
			}
		},
		// 清空内容
		clearContent() {
			this.setContent('')
			this.syncContent()
		},
		// 编辑区域获得焦点，方便触发格式化命令
		focusEditor() {
			if (this.$refs.editor) {
				this.$refs.editor.focus()
				this.restoreSelection()
			}
		},
		// 监听输入事件，将HTML回写给父组件
		handleInput() {
			this.syncContent()
		},
		// 记录当前的光标选区，便于插入图片或文本
		saveSelection() {
			const selection = window.getSelection()
			if (selection.rangeCount > 0) {
				this.currentRange = selection.getRangeAt(0)
			}
		},
		// 当外部操作打断焦点时，恢复光标
		restoreSelection() {
			if (!this.currentRange) {
				return
			}
			const selection = window.getSelection()
			selection.removeAllRanges()
			selection.addRange(this.currentRange)
		},
		// 同步内容到父组件
		syncContent() {
			if (!this.$refs.editor) {
				return
			}
			this.innerHTML = this.$refs.editor.innerHTML
			this.$emit('input', this.innerHTML)
			this.$emit('change', this.innerHTML)
		},
		// 点击上传按钮
		triggerUpload() {
			if (this.uploading) {
				return
			}
			this.$refs.fileInput.value = ''
			this.$refs.fileInput.click()
		},
		// 选择图片后上传，并插入富文本
		async handleUpload(event) {
			const file = event.target.files && event.target.files[0]
			if (!file) {
				return
			}
			await this.uploadImage(file)
			event.target.value = ''
		},
		// 将图片上传到后端
		async uploadImage(file) {
			const isImage = file.type && file.type.indexOf('image/') === 0
			if (!isImage) {
				this.$Message.error('仅支持上传图片文件')
				return
			}
			this.uploading = true
			try {
				const formData = new FormData()
				formData.append('file', file)
				const res = await upload(formData)
				const fileUrl = res.data
				if (!fileUrl) {
					throw new Error('上传接口未返回图片地址')
				}
				this.insertImage(fileUrl)
				this.$Message.success('图片上传成功')
			} catch (error) {
				this.$Message.error(error.msg || '图片上传失败，请稍后重试')
			} finally {
				this.uploading = false
			}
		},
		// 插入图片到当前光标位置
		insertImage(url) {
			this.focusEditor()
			document.execCommand('insertImage', false, url)
			this.syncContent()
		},
	},
}
</script>
<style scoped>
.rich-editor {
	width: 100%;
}

.rich-editor__toolbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 10px;
}

.rich-editor__content {
	height: 100%;
	padding: 12px;
	border: 1px solid #dcdee2;
	border-radius: 8px;
	line-height: 1.6;
	overflow-y: auto;
}

.rich-editor__content:focus {
	outline: none;
	border-color: #2d8cf0;
	box-shadow: 0 0 0 2px rgba(45, 140, 240, 0.1);
}

.rich-editor__content:empty:before {
	content: attr(data-placeholder);
	color: #c5c8ce;
}

.rich-editor__upload {
	margin-left: 16px;
}

.rich-editor__toolbar-group .ivu-btn {
	display: inline-flex;
	align-items: center;
	padding: 0 12px;
}

.rich-editor__toolbar-group .ivu-btn .ivu-icon {
	margin-right: 4px;
}

.rich-editor__file {
	display: none;
}
</style>
