Files
users/components/documentation/document-generator.tsx
v0 2408d50cb0 refactor: overhaul UI for streamlined user experience
Redesign navigation, home overview, user portrait, and valuation pages
with improved functionality and responsive design.

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
2025-07-18 13:47:12 +00:00

177 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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>
)
}