1 changed files with 80 additions and 0 deletions
@ -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…
Reference in new issue