Files
ojnext/src/shared/components/TextEditor.vue
yuetsh 4ecd7bb229
Some checks failed
Deploy / deploy (build, debian, 22, /root/OJDeploy/data/clientnext) (push) Has been cancelled
Deploy / deploy (build:staging, school, 8822, /root/OJ/data/dist) (push) Has been cancelled
fix3
2026-05-07 02:27:09 -06:00

148 lines
2.8 KiB
Vue

<script setup lang="ts">
import type {
IDomEditor,
IEditorConfig,
IToolbarConfig,
} from "@wangeditor-next/editor"
import { Editor, Toolbar } from "@wangeditor-next/editor-for-vue"
import "@wangeditor-next/editor/dist/css/style.css"
import { uploadImage } from "../../admin/api"
interface Props {
title: string
simple?: boolean
minHeight?: number
}
const rawHtml = defineModel<string>("value")
type InsertFnType = (url: string, alt: string, href: string) => void
const props = withDefaults(defineProps<Props>(), {
minHeight: 0,
simple: false,
})
const message = useMessage()
const editorRef = shallowRef<IDomEditor>()
const toolbarEditorRef = shallowRef<IDomEditor>()
const toolbarConfig: Partial<IToolbarConfig> = {
toolbarKeys: [
"blockquote",
"headerSelect",
"fontSize",
"lineHeight",
"|",
"bold",
"underline",
"italic",
"through",
"color",
"bgColor",
"|",
"bulletedList",
"numberedList",
"justifyLeft",
"justifyCenter",
"justifyRight",
"|",
"uploadImage",
"emotion",
"insertLink",
"insertTable",
"divider",
"|",
"clearStyle",
"undo",
"redo",
],
}
const toolbarConfigSimple: Partial<IToolbarConfig> = {
toolbarKeys: [
"bold",
"color",
"bgColor",
"emotion",
"uploadImage",
"insertLink",
"clearStyle",
"undo",
"redo",
],
}
const editorConfig: Partial<IEditorConfig> = {
scroll: false,
MENU_CONF: {
// @ts-ignore
uploadImage: { customUpload },
},
}
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor) editor.destroy()
})
function onClick() {
if (!editorRef.value) return
editorRef.value.blur()
editorRef.value.focus()
}
async function handleCreated(editor: IDomEditor) {
editorRef.value = editor
await nextTick()
toolbarEditorRef.value = editor
}
async function customUpload(file: File, insertFn: InsertFnType) {
const path = await uploadImage(file)
if (!path) {
message.error("图片上传失败")
return
}
const url = path
const alt = "图片"
const href = ""
insertFn(url, alt, href)
}
</script>
<template>
<div class="title" v-if="props.title">{{ props.title }}</div>
<div class="editorWrapper">
<Toolbar
class="toolbar"
:editor="toolbarEditorRef"
:defaultConfig="props.simple ? toolbarConfigSimple : toolbarConfig"
mode="simple"
/>
<Editor
@click="onClick"
:style="{ minHeight: props.minHeight + 'px' }"
v-model="rawHtml"
:defaultConfig="editorConfig"
mode="simple"
@onCreated="handleCreated"
/>
</div>
</template>
<style scoped>
.title {
margin-bottom: 12px;
}
.toolbar {
border-bottom: 1px solid #ddd;
}
.editorWrapper {
border: 1px solid #ddd;
margin-bottom: 20px;
}
</style>