diff --git a/src/components/editor/WechatEditor.tsx b/src/components/editor/WechatEditor.tsx index 2e41318..47566b3 100644 --- a/src/components/editor/WechatEditor.tsx +++ b/src/components/editor/WechatEditor.tsx @@ -4,7 +4,6 @@ import { useState, useCallback, useRef, useEffect } from 'react' import { useToast } from '@/components/ui/use-toast' import { ToastAction } from '@/components/ui/toast' import { type RendererOptions } from '@/lib/markdown' -import { useEditorSync } from './hooks/useEditorSync' import { useAutoSave } from './hooks/useAutoSave' import { EditorToolbar } from './components/EditorToolbar' import { EditorPreview } from './components/EditorPreview' @@ -20,6 +19,11 @@ import { useEditorKeyboard } from './hooks/useEditorKeyboard' import { useScrollSync } from './hooks/useScrollSync' import { useWordStats } from './hooks/useWordStats' import { useCopy } from './hooks/useCopy' +import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs' +import { Button } from '@/components/ui/button' +import { Copy } from 'lucide-react' +import { MobileEditor } from './components/MobileEditor' +import { DesktopEditor } from './components/DesktopEditor' export default function WechatEditor() { const { toast } = useToast() @@ -37,10 +41,22 @@ export default function WechatEditor() { const [codeTheme, setCodeTheme] = useLocalStorage('code-theme', codeThemes[0].id) // 使用自定义 hooks - const { handleScroll } = useEditorSync(editorRef) const { handleEditorChange } = useAutoSave(value, setIsDraft) const { handleEditorScroll } = useScrollSync() + // 清除编辑器内容 + const handleClear = useCallback(() => { + if (window.confirm('确定要清除所有内容吗?')) { + setValue('') + handleEditorChange('') + toast({ + title: "已清除", + description: "编辑器内容已清除", + duration: 2000 + }) + } + }, [handleEditorChange, toast]) + // 手动保存 const handleSave = useCallback(() => { try { @@ -97,12 +113,29 @@ export default function WechatEditor() { }) }, [handleEditorChange]) - const { handleCopy } = useCopy() + const { copyToClipboard } = useCopy() - // 处理复制 - const onCopy = useCallback(async () => { - return handleCopy(window.getSelection(), previewContent) - }, [handleCopy, previewContent]) + const handleCopy = useCallback(async (): Promise => { + const contentElement = previewRef.current?.querySelector('.preview-content') as HTMLElement | null + if (!contentElement) return false + + const success = await copyToClipboard(contentElement) + if (success) { + toast({ + title: "复制成功", + description: "内容已复制,可直接粘贴到公众号编辑器", + duration: 2000 + }) + } else { + toast({ + variant: "destructive", + title: "复制失败", + description: "无法访问剪贴板,请检查浏览器权限", + duration: 2000 + }) + } + return success + }, [copyToClipboard, toast, previewRef]) // 处理放弃草稿 const handleDiscardDraft = useCallback(() => { @@ -192,19 +225,6 @@ export default function WechatEditor() { setStyleOptions({}) }, []) - // 清除编辑器内容 - const handleClear = useCallback(() => { - if (window.confirm('确定要清除所有内容吗?')) { - setValue('') - handleEditorChange('') - toast({ - title: "已清除", - description: "编辑器内容已清除", - duration: 2000 - }) - } - }, [handleEditorChange, toast]) - // 检测是否为移动设备 const isMobile = useCallback(() => { if (typeof window === 'undefined') return false @@ -245,141 +265,72 @@ export default function WechatEditor() { const { wordCount, readingTime } = useWordStats(value) return ( -
-
- setValue(value)} - onStyleOptionsChange={setStyleOptions} - onPreviewToggle={() => setShowPreview(!showPreview)} - styleOptions={styleOptions} - wordCount={wordCount} - readingTime={readingTime} - codeTheme={codeTheme} - onCodeThemeChange={setCodeTheme} - /> -
- -
- {/* Mobile View */} -
-
-
- -
-
- - -
-
-
-
-
t.id === selectedTemplate)?.styles - )} - > -