Files
users/components/documentation/document-generator.tsx

177 lines
5.7 KiB
TypeScript
Raw Normal View History

"use client"
import { useState, useEffect } from "react"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { Alert, AlertDescription } from "@/components/ui/alert"
import { Loader2, FileText, AlertTriangle } from "lucide-react"
import { generateDocx } from "@/lib/documentation/docx-generator"
interface DocumentSection {
title: string
path: string
description: string
screenshot: string
}
interface DocumentGeneratorProps {
pages: Array<{ path: string; title: string; description: string }>
screenshots: Record<string, string>
onDocumentGenerated: (url: string) => void
}
export default function DocumentGenerator({ pages, screenshots, onDocumentGenerated }: DocumentGeneratorProps) {
const [isGenerating, setIsGenerating] = useState(false)
const [error, setError] = useState<string | null>(null)
const [sections, setSections] = useState<DocumentSection[]>([])
const [descriptions, setDescriptions] = useState<Record<string, string>>({})
// 初始化页面描述
useEffect(() => {
const initialDescriptions: Record<string, string> = {}
pages.forEach((page) => {
initialDescriptions[page.path] = page.description || ""
})
setDescriptions(initialDescriptions)
}, [pages])
// 更新页面描述
const updateDescription = (path: string, description: string) => {
setDescriptions((prev) => ({
...prev,
[path]: description,
}))
}
// 准备文档部分
useEffect(() => {
const newSections = pages
.filter((page) => screenshots[page.path])
.map((page) => ({
title: page.title,
path: page.path,
description: descriptions[page.path] || page.description || "",
screenshot: screenshots[page.path],
}))
setSections(newSections)
}, [pages, screenshots, descriptions])
// 生成文档
const generateDocument = async () => {
if (sections.length === 0) {
setError("没有可用的截图,请先捕获页面截图")
return
}
setIsGenerating(true)
setError(null)
try {
console.log("开始生成文档...")
console.log("文档部分数量:", sections.length)
// 准备文档数据
const documentData = {
title: "用户数据资产中台使用手册",
author: "系统管理员",
date: new Date().toLocaleDateString("zh-CN"),
sections: sections,
}
console.log("文档数据准备完成")
// 生成Word文档
const docxUrl = await generateDocx(documentData)
console.log("文档生成成功:", docxUrl)
// 调用回调函数
onDocumentGenerated(docxUrl)
} catch (error) {
console.error("生成文档时出错:", error)
setError(`生成文档时出错: ${error instanceof Error ? error.message : String(error)}`)
} finally {
setIsGenerating(false)
}
}
return (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-xl font-semibold"></h2>
<Button
onClick={generateDocument}
disabled={isGenerating || sections.length === 0}
className="flex items-center gap-2"
>
{isGenerating ? (
<>
<Loader2 className="h-4 w-4 animate-spin" />
...
</>
) : (
<>
<FileText className="h-4 w-4" />
</>
)}
</Button>
</div>
{error && (
<Alert variant="destructive">
<AlertTriangle className="h-4 w-4" />
<AlertDescription>{error}</AlertDescription>
</Alert>
)}
{sections.length === 0 ? (
<div className="text-center py-8">
<p className="text-gray-500"></p>
<p className="text-sm text-gray-400 mt-1"></p>
</div>
) : (
<div className="space-y-4">
<p className="text-sm text-gray-500">
{sections.length}
</p>
{sections.map((section) => (
<Card key={section.path} className="overflow-hidden">
<CardContent className="p-4">
<div className="flex flex-col md:flex-row gap-4">
<div className="md:w-1/3">
<div className="border rounded-md overflow-hidden">
<img
src={section.screenshot || "/placeholder.svg"}
alt={section.title}
className="w-full h-auto object-contain"
/>
</div>
<p className="text-sm font-medium mt-2">{section.title}</p>
<p className="text-xs text-gray-500">{section.path}</p>
</div>
<div className="md:w-2/3">
<div className="space-y-2">
<Label htmlFor={`desc-${section.path}`}></Label>
<Textarea
id={`desc-${section.path}`}
value={descriptions[section.path] || ""}
onChange={(e) => updateDescription(section.path, e.target.value)}
placeholder="输入此页面的详细描述"
rows={6}
/>
</div>
</div>
</div>
</CardContent>
</Card>
))}
</div>
)}
</div>
)
}