You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
99 lines
2.4 KiB
99 lines
2.4 KiB
<script setup lang="ts">
|
|
import { ref, onMounted, watch } from 'vue'
|
|
import Quill from 'quill'
|
|
import 'quill/dist/quill.snow.css'
|
|
import { mediaApi } from '@/api/client'
|
|
|
|
const props = defineProps<{
|
|
modelValue: string
|
|
}>()
|
|
const emit = defineEmits<{
|
|
(e: 'update:modelValue', value: string): void
|
|
}>()
|
|
|
|
const editorContainer = ref<HTMLDivElement>()
|
|
let quill: Quill | null = null
|
|
|
|
onMounted(() => {
|
|
if (!editorContainer.value) return
|
|
|
|
quill = new Quill(editorContainer.value, {
|
|
theme: 'snow',
|
|
placeholder: '开始写作...',
|
|
modules: {
|
|
toolbar: [
|
|
[{ header: [1, 2, false] }],
|
|
['bold', 'italic', 'underline', 'strike'],
|
|
['blockquote', 'code-block'],
|
|
[{ list: 'ordered' }, { list: 'bullet' }],
|
|
[{ indent: '-1' }, { indent: '+1' }],
|
|
['link', 'image'],
|
|
['clean']
|
|
]
|
|
}
|
|
})
|
|
|
|
quill.root.innerHTML = props.modelValue
|
|
|
|
quill.on('text-change', () => {
|
|
emit('update:modelValue', quill!.root.innerHTML)
|
|
})
|
|
|
|
const toolbar = quill.getModule('toolbar') as any
|
|
toolbar.addHandler('image', () => {
|
|
const input = document.createElement('input')
|
|
input.setAttribute('type', 'file')
|
|
input.setAttribute('accept', 'image/*')
|
|
input.click()
|
|
input.onchange = async () => {
|
|
const file = input.files?.[0]
|
|
if (file) {
|
|
try {
|
|
const resp = await mediaApi.apiMediaUploadPost(file, 'images')
|
|
const stored = resp.data.data
|
|
const url = stored?.url
|
|
if (url && quill) {
|
|
const sel = quill.getSelection()
|
|
const index = sel ? sel.index : 0
|
|
quill.insertEmbed(index, 'image', url)
|
|
}
|
|
} catch (e) {
|
|
console.error(e)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
watch(() => props.modelValue, (val) => {
|
|
if (quill && val !== quill.root.innerHTML) {
|
|
quill.root.innerHTML = val
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div ref="editorContainer" class="quill-editor" />
|
|
</template>
|
|
|
|
<style scoped>
|
|
.quill-editor {
|
|
min-height: 400px;
|
|
background: var(--ac-bg-card, #fff);
|
|
}
|
|
.quill-editor :deep(.ql-editor) {
|
|
min-height: 400px;
|
|
font-size: 16px;
|
|
line-height: 1.8;
|
|
}
|
|
.quill-editor :deep(.ql-toolbar) {
|
|
border-color: var(--ac-border, #d4c4b0);
|
|
background: var(--ac-surface, #faf8f5);
|
|
}
|
|
.quill-editor :deep(.ql-container) {
|
|
border-color: var(--ac-border, #d4c4b0);
|
|
}
|
|
.quill-editor :deep(.ql-editor.ql-blank::before) {
|
|
color: var(--ac-text-disabled);
|
|
}
|
|
</style>
|