This commit is contained in:
1 parent
1a4466d85d
commit
2f41bda41e
1 file changed
+84
-12
@@ -1,10 +1,12 @@
|
||||
<script lang="ts">
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { EditorView, basicSetup } from 'codemirror';
|
||||
import { EditorState } from '@codemirror/state';
|
||||
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
||||
import { languages } from '@codemirror/language-data';
|
||||
import { placeholder as cmPlaceholder } from '@codemirror/view';
|
||||
import { addToast } from '$lib/stores/toast.svelte';
|
||||
|
||||
let { value = $bindable(''), placeholderText = '支持 Markdown 格式...' } = $props();
|
||||
|
||||
@@ -12,6 +14,40 @@
|
||||
let view: EditorView;
|
||||
let isUpdating = false;
|
||||
|
||||
let showImageMenu = $state(false);
|
||||
let fileInput: HTMLInputElement;
|
||||
let isUploadingImage = $state(false);
|
||||
|
||||
async function handleImageUpload(e: Event) {
|
||||
const input = e.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
if (!file) return;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
isUploadingImage = true;
|
||||
try {
|
||||
const res = await fetch('/admin/api/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
const data = (await res.json()) as any;
|
||||
if (data.success) {
|
||||
insertAtCursor('`, file.name || '图片');
|
||||
addToast('图片上传成功', 'success');
|
||||
} else {
|
||||
addToast(data.error || '上传失败', 'error');
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
addToast('网络错误,上传失败', 'error');
|
||||
} finally {
|
||||
isUploadingImage = false;
|
||||
input.value = '';
|
||||
showImageMenu = false;
|
||||
}
|
||||
}
|
||||
const customTheme = EditorView.theme({
|
||||
'&': {
|
||||
color: 'var(--text-color)',
|
||||
@@ -228,19 +264,55 @@
|
||||
></path></svg
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="md-btn"
|
||||
onclick={() => insertAtCursor('', '图片描述')}
|
||||
title="图片"
|
||||
>
|
||||
<svg viewBox="0 0 24 24"
|
||||
><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><polygon
|
||||
points="6 21, 10 13, 13 16.5, 16.5 9.5, 19 21"
|
||||
style="fill: currentColor; stroke: currentColor; stroke-linejoin: round; stroke-width: 1.5;"
|
||||
></polygon></svg
|
||||
<div class="toolbar-dropdown-wrapper">
|
||||
{#if showImageMenu}
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<!-- svelte-ignore a11y_interactive_supports_focus -->
|
||||
<div class="dropdown-overlay" onclick={() => (showImageMenu = false)} role="button"></div>
|
||||
{/if}
|
||||
<button
|
||||
type="button"
|
||||
class="md-btn"
|
||||
onclick={() => (showImageMenu = !showImageMenu)}
|
||||
title="图片"
|
||||
>
|
||||
</button>
|
||||
<svg viewBox="0 0 24 24"
|
||||
><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><polygon
|
||||
points="6 21, 10 13, 13 16.5, 16.5 9.5, 19 21"
|
||||
style="fill: currentColor; stroke: currentColor; stroke-linejoin: round; stroke-width: 1.5;"
|
||||
></polygon></svg
|
||||
>
|
||||
</button>
|
||||
{#if showImageMenu}
|
||||
<div class="toolbar-dropdown">
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-item"
|
||||
onclick={() => {
|
||||
insertAtCursor('', '图片描述');
|
||||
showImageMenu = false;
|
||||
}}
|
||||
>
|
||||
插入图片链接
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="dropdown-item"
|
||||
onclick={() => fileInput.click()}
|
||||
disabled={isUploadingImage}
|
||||
>
|
||||
{isUploadingImage ? '正在上传...' : '上传本地图片'}
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
style="display:none;"
|
||||
bind:this={fileInput}
|
||||
onchange={handleImageUpload}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="md-btn"
|
||||
|
||||
Reference in new issue
Block a user