Browse Source

feat(editor): add PostBodyMarkdownEditor with md-editor-v3 and upload

Made-with: Cursor
main
npmrun 11 hours ago
parent
commit
2d63b144ca
  1. 80
      app/components/PostBodyMarkdownEditor.vue

80
app/components/PostBodyMarkdownEditor.vue

@ -0,0 +1,80 @@
<script setup lang="ts">
import { MdEditor } from 'md-editor-v3'
import 'md-editor-v3/lib/style.css'
import { request, unwrapApiBody, type ApiResponse } from '~/utils/http/factory'
const props = defineProps<{
modelValue: string
}>()
const emit = defineEmits<{
'update:modelValue': [string]
}>()
const toast = useToast()
const editorId = `post-body-md-${useId()}`
const local = computed({
get: () => props.modelValue,
set: (v: string) => emit('update:modelValue', v),
})
function extractUploadError(e: unknown): string {
if (e && typeof e === 'object') {
const fe = e as {
statusMessage?: string
message?: string
data?: { message?: string }
}
if (typeof fe.statusMessage === 'string' && fe.statusMessage.length) {
return fe.statusMessage
}
if (typeof fe.data?.message === 'string' && fe.data.message.length) {
return fe.data.message
}
if (typeof fe.message === 'string' && fe.message.length) {
return fe.message
}
}
return '图片上传失败'
}
async function onUploadImg(files: File[], callback: (urls: string[]) => void) {
const form = new FormData()
for (const f of files) {
form.append('file', f)
}
try {
const res = await request<ApiResponse<{ files: { url: string }[] }>>('/api/file/upload', {
method: 'POST',
body: form,
})
const { files: uploaded } = unwrapApiBody(res)
callback(uploaded.map((x) => x.url))
} catch (e: unknown) {
toast.add({ title: extractUploadError(e), color: 'error' })
callback([])
}
}
</script>
<template>
<ClientOnly>
<MdEditor
:id="editorId"
v-model="local"
language="zh-CN"
:preview="true"
preview-theme="github"
theme="light"
:on-upload-img="onUploadImg"
:style="{ height: 'min(72vh, 720px)' }"
class="w-full rounded-lg overflow-hidden ring ring-default"
/>
<template #fallback>
<div class="text-muted text-sm py-12 text-center border border-default rounded-lg">
编辑器加载中
</div>
</template>
</ClientOnly>
</template>
Loading…
Cancel
Save