重构代码,修改统计字数
This commit is contained in:
		
							parent
							
								
									97efa6ccdd
								
							
						
					
					
						commit
						bb60f67316
					
				@ -23,9 +23,10 @@ import {
 | 
			
		||||
  AlertDialogTrigger,
 | 
			
		||||
} from "@/components/ui/alert-dialog"
 | 
			
		||||
import { ScrollArea } from '@/components/ui/scroll-area'
 | 
			
		||||
import { FileText, Trash2, Menu, Plus, Save } from 'lucide-react'
 | 
			
		||||
import { FileText, Trash2, Menu, Plus, Save, Edit2, Check } from 'lucide-react'
 | 
			
		||||
import { useToast } from '@/components/ui/use-toast'
 | 
			
		||||
import { ToastAction } from '@/components/ui/toast'
 | 
			
		||||
import { Input } from '@/components/ui/input'
 | 
			
		||||
 | 
			
		||||
interface Article {
 | 
			
		||||
  id: string
 | 
			
		||||
@ -46,6 +47,9 @@ export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProp
 | 
			
		||||
  const { toast } = useToast()
 | 
			
		||||
  const [articles, setArticles] = useState<Article[]>([])
 | 
			
		||||
  const [articleToDelete, setArticleToDelete] = useState<Article | null>(null)
 | 
			
		||||
  const [editingId, setEditingId] = useState<string | null>(null)
 | 
			
		||||
  const [editingTitle, setEditingTitle] = useState('')
 | 
			
		||||
  const [isOpen, setIsOpen] = useState(false)
 | 
			
		||||
 | 
			
		||||
  // 加载文章列表
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
@ -119,6 +123,7 @@ export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProp
 | 
			
		||||
    // 如果有外部传入的新建处理函数,优先使用
 | 
			
		||||
    if (onNew) {
 | 
			
		||||
      onNew()
 | 
			
		||||
      setIsOpen(false)
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -126,23 +131,92 @@ export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProp
 | 
			
		||||
    const newArticle: Article = {
 | 
			
		||||
      id: Date.now().toString(),
 | 
			
		||||
      title: '新文章',
 | 
			
		||||
      content: '# 新文章\n\n开始写作...',
 | 
			
		||||
      content: `# 新文章
 | 
			
		||||
 | 
			
		||||
## 简介
 | 
			
		||||
在这里写文章的简介...
 | 
			
		||||
 | 
			
		||||
## 正文
 | 
			
		||||
开始写作你的精彩内容...
 | 
			
		||||
 | 
			
		||||
## 总结
 | 
			
		||||
在这里总结文章的主要观点...
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
> 作者:[你的名字]
 | 
			
		||||
> 日期:${new Date().toLocaleDateString()}
 | 
			
		||||
`,
 | 
			
		||||
      template: 'default',
 | 
			
		||||
      createdAt: Date.now(),
 | 
			
		||||
      updatedAt: Date.now()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 保存新文章到本地存储
 | 
			
		||||
    const updatedArticles = [newArticle, ...articles]
 | 
			
		||||
    setArticles(updatedArticles)
 | 
			
		||||
    localStorage.setItem('wechat_articles', JSON.stringify(updatedArticles))
 | 
			
		||||
 | 
			
		||||
    // 选中新文章并关闭列表
 | 
			
		||||
    onSelect(newArticle)
 | 
			
		||||
    setIsOpen(false)
 | 
			
		||||
    
 | 
			
		||||
    toast({
 | 
			
		||||
      title: "新建成功",
 | 
			
		||||
      description: "已创建新文章",
 | 
			
		||||
      description: "已创建新文章,开始写作吧!",
 | 
			
		||||
      duration: 2000
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 开始重命名
 | 
			
		||||
  const startRename = (article: Article) => {
 | 
			
		||||
    setEditingId(article.id)
 | 
			
		||||
    setEditingTitle(article.title)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 保存重命名
 | 
			
		||||
  const saveRename = (article: Article) => {
 | 
			
		||||
    if (!editingTitle.trim()) {
 | 
			
		||||
      toast({
 | 
			
		||||
        variant: "destructive",
 | 
			
		||||
        title: "重命名失败",
 | 
			
		||||
        description: "文章标题不能为空",
 | 
			
		||||
        duration: 2000
 | 
			
		||||
      })
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const updatedArticles = articles.map(a => {
 | 
			
		||||
      if (a.id === article.id) {
 | 
			
		||||
        return {
 | 
			
		||||
          ...a,
 | 
			
		||||
          title: editingTitle.trim(),
 | 
			
		||||
          updatedAt: Date.now()
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return a
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    setArticles(updatedArticles)
 | 
			
		||||
    localStorage.setItem('wechat_articles', JSON.stringify(updatedArticles))
 | 
			
		||||
    setEditingId(null)
 | 
			
		||||
    setEditingTitle('')
 | 
			
		||||
 | 
			
		||||
    toast({
 | 
			
		||||
      title: "重命名成功",
 | 
			
		||||
      description: `文章已重命名为"${editingTitle.trim()}"`,
 | 
			
		||||
      duration: 2000
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 取消重命名
 | 
			
		||||
  const cancelRename = () => {
 | 
			
		||||
    setEditingId(null)
 | 
			
		||||
    setEditingTitle('')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Sheet>
 | 
			
		||||
      <Sheet open={isOpen} onOpenChange={setIsOpen}>
 | 
			
		||||
        <SheetTrigger asChild>
 | 
			
		||||
          <Button variant="ghost" size="icon" className="relative">
 | 
			
		||||
            <Menu className="h-5 w-5" />
 | 
			
		||||
@ -175,27 +249,66 @@ export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProp
 | 
			
		||||
                  key={article.id}
 | 
			
		||||
                  className="flex items-center justify-between p-2 rounded-md hover:bg-muted group"
 | 
			
		||||
                >
 | 
			
		||||
                  <button
 | 
			
		||||
                    onClick={() => onSelect(article)}
 | 
			
		||||
                    className="flex items-center gap-2 flex-1 text-left"
 | 
			
		||||
                  >
 | 
			
		||||
                    <FileText className="h-4 w-4 text-muted-foreground" />
 | 
			
		||||
                    <div className="flex-1 min-w-0">
 | 
			
		||||
                      <div className="font-medium truncate">{article.title}</div>
 | 
			
		||||
                      <div className="text-xs text-muted-foreground">
 | 
			
		||||
                        {new Date(article.updatedAt).toLocaleString()}
 | 
			
		||||
                      </div>
 | 
			
		||||
                  {editingId === article.id ? (
 | 
			
		||||
                    <div className="flex items-center gap-2 flex-1">
 | 
			
		||||
                      <Input
 | 
			
		||||
                        value={editingTitle}
 | 
			
		||||
                        onChange={(e) => setEditingTitle(e.target.value)}
 | 
			
		||||
                        onKeyDown={(e) => {
 | 
			
		||||
                          if (e.key === 'Enter') {
 | 
			
		||||
                            saveRename(article)
 | 
			
		||||
                          } else if (e.key === 'Escape') {
 | 
			
		||||
                            cancelRename()
 | 
			
		||||
                          }
 | 
			
		||||
                        }}
 | 
			
		||||
                        className="h-8"
 | 
			
		||||
                        autoFocus
 | 
			
		||||
                      />
 | 
			
		||||
                      <Button
 | 
			
		||||
                        variant="ghost"
 | 
			
		||||
                        size="icon"
 | 
			
		||||
                        onClick={() => saveRename(article)}
 | 
			
		||||
                        className="h-8 w-8"
 | 
			
		||||
                      >
 | 
			
		||||
                        <Check className="h-4 w-4" />
 | 
			
		||||
                      </Button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </button>
 | 
			
		||||
                  <Button
 | 
			
		||||
                    variant="ghost"
 | 
			
		||||
                    size="icon"
 | 
			
		||||
                    className="shrink-0 hover:bg-destructive/10 hover:text-destructive transition-colors"
 | 
			
		||||
                    onClick={() => deleteArticle(article)}
 | 
			
		||||
                  >
 | 
			
		||||
                    <Trash2 className="h-4 w-4 text-destructive" />
 | 
			
		||||
                    <span className="sr-only">删除</span>
 | 
			
		||||
                  </Button>
 | 
			
		||||
                  ) : (
 | 
			
		||||
                    <>
 | 
			
		||||
                      <button
 | 
			
		||||
                        onClick={() => onSelect(article)}
 | 
			
		||||
                        className="flex items-center gap-2 flex-1 text-left"
 | 
			
		||||
                      >
 | 
			
		||||
                        <FileText className="h-4 w-4 text-muted-foreground" />
 | 
			
		||||
                        <div className="flex-1 min-w-0">
 | 
			
		||||
                          <div className="font-medium truncate">{article.title}</div>
 | 
			
		||||
                          <div className="text-xs text-muted-foreground">
 | 
			
		||||
                            {new Date(article.updatedAt).toLocaleString()}
 | 
			
		||||
                          </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                      </button>
 | 
			
		||||
                      <div className="flex items-center gap-1">
 | 
			
		||||
                        <Button
 | 
			
		||||
                          variant="ghost"
 | 
			
		||||
                          size="icon"
 | 
			
		||||
                          className="h-8 w-8 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity"
 | 
			
		||||
                          onClick={() => startRename(article)}
 | 
			
		||||
                        >
 | 
			
		||||
                          <Edit2 className="h-4 w-4" />
 | 
			
		||||
                          <span className="sr-only">重命名</span>
 | 
			
		||||
                        </Button>
 | 
			
		||||
                        <Button
 | 
			
		||||
                          variant="ghost"
 | 
			
		||||
                          size="icon"
 | 
			
		||||
                          className="h-8 w-8 shrink-0 hover:bg-destructive/10 hover:text-destructive transition-colors"
 | 
			
		||||
                          onClick={() => deleteArticle(article)}
 | 
			
		||||
                        >
 | 
			
		||||
                          <Trash2 className="h-4 w-4 text-destructive" />
 | 
			
		||||
                          <span className="sr-only">删除</span>
 | 
			
		||||
                        </Button>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </>
 | 
			
		||||
                  )}
 | 
			
		||||
                </div>
 | 
			
		||||
              ))}
 | 
			
		||||
              {articles.length === 0 && (
 | 
			
		||||
@ -6,7 +6,7 @@ import { cn } from '@/lib/utils'
 | 
			
		||||
import { WechatStylePicker } from '../../template/WechatStylePicker'
 | 
			
		||||
import { TemplateManager } from '../../template/TemplateManager'
 | 
			
		||||
import { StyleConfigDialog } from '../StyleConfigDialog'
 | 
			
		||||
import { ArticleList } from '../ArticleList'
 | 
			
		||||
import { ArticleList } from '@/components/ArticleList'
 | 
			
		||||
import { type Article } from '../constants'
 | 
			
		||||
import { type RendererOptions } from '@/lib/markdown'
 | 
			
		||||
import { ThemeToggle } from '@/components/theme/ThemeToggle'
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user