新增資料庫架構

This commit is contained in:
2025-07-19 02:12:37 +08:00
parent e3832acfa8
commit 924f03c3d7
45 changed files with 12858 additions and 324 deletions

View File

@@ -0,0 +1,161 @@
"use client"
import { Alert, AlertDescription } from "@/components/ui/alert"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import { AlertTriangle, Lightbulb, CheckCircle, XCircle, RefreshCw } from "lucide-react"
import type { ModerationResult } from "@/lib/content-moderation"
interface ContentModerationFeedbackProps {
result: ModerationResult
onRetry: () => void
className?: string
}
export default function ContentModerationFeedback({ result, onRetry, className = "" }: ContentModerationFeedbackProps) {
if (result.issues.length === 0 && result.suggestions.length === 0) {
return null
}
const getSeverityColor = (severity: string) => {
switch (severity) {
case "high":
return "border-red-500/50 bg-red-900/20"
case "medium":
return "border-yellow-500/50 bg-yellow-900/20"
case "low":
return "border-blue-500/50 bg-blue-900/20"
default:
return "border-slate-500/50 bg-slate-900/20"
}
}
const getSeverityIcon = (severity: string) => {
switch (severity) {
case "high":
return <XCircle className="w-5 h-5 text-red-400" />
case "medium":
return <AlertTriangle className="w-5 h-5 text-yellow-400" />
case "low":
return <Lightbulb className="w-5 h-5 text-blue-400" />
default:
return <CheckCircle className="w-5 h-5 text-green-400" />
}
}
const getSeverityTitle = (severity: string) => {
switch (severity) {
case "high":
return "內容審核未通過"
case "medium":
return "內容建議優化"
case "low":
return "內容建議"
default:
return "內容檢查"
}
}
return (
<Card className={`${getSeverityColor(result.severity)} backdrop-blur-sm border ${className}`}>
<CardContent className="p-4 space-y-4">
{/* 標題區域 */}
<div className="flex items-center gap-3">
{getSeverityIcon(result.severity)}
<div className="flex-1">
<h4 className="font-semibold text-white text-sm md:text-base">{getSeverityTitle(result.severity)}</h4>
<div className="flex items-center gap-2 mt-1">
<Badge
className={`text-xs px-2 py-0.5 ${
result.severity === "high"
? "bg-red-500/20 text-red-200 border-red-400/30"
: result.severity === "medium"
? "bg-yellow-500/20 text-yellow-200 border-yellow-400/30"
: "bg-blue-500/20 text-blue-200 border-blue-400/30"
}`}
>
{result.severity === "high" ? "需要修改" : result.severity === "medium" ? "建議優化" : "輕微建議"}
</Badge>
{!result.isAppropriate && (
<Badge className="bg-red-500/20 text-red-200 border-red-400/30 text-xs px-2 py-0.5"></Badge>
)}
</div>
</div>
{!result.isAppropriate && (
<Button
variant="ghost"
size="sm"
onClick={onRetry}
className="text-blue-200 hover:text-white hover:bg-blue-800/50 px-3"
>
<RefreshCw className="w-4 h-4 mr-1" />
</Button>
)}
</div>
{/* 問題列表 */}
{result.issues.length > 0 && (
<div className="space-y-2">
<h5 className="text-sm font-medium text-red-200 flex items-center gap-2">
<AlertTriangle className="w-4 h-4" />
</h5>
<ul className="space-y-1">
{result.issues.map((issue, index) => (
<li key={index} className="text-sm text-red-100 flex items-start gap-2">
<div className="w-1.5 h-1.5 bg-red-400 rounded-full mt-2 flex-shrink-0"></div>
{issue}
</li>
))}
</ul>
</div>
)}
{/* 建議列表 */}
{result.suggestions.length > 0 && (
<div className="space-y-2">
<h5 className="text-sm font-medium text-blue-200 flex items-center gap-2">
<Lightbulb className="w-4 h-4" />
</h5>
<ul className="space-y-1">
{result.suggestions.map((suggestion, index) => (
<li key={index} className="text-sm text-blue-100 flex items-start gap-2">
<div className="w-1.5 h-1.5 bg-blue-400 rounded-full mt-2 flex-shrink-0"></div>
{suggestion}
</li>
))}
</ul>
</div>
)}
{/* 被阻擋的詞彙 */}
{result.blockedWords.length > 0 && (
<div className="space-y-2">
<h5 className="text-sm font-medium text-red-200"></h5>
<div className="flex flex-wrap gap-2">
{result.blockedWords.map((word, index) => (
<Badge key={index} className="bg-red-500/20 text-red-200 border-red-400/30 text-xs px-2 py-1">
{word}
</Badge>
))}
</div>
</div>
)}
{/* 鼓勵訊息 */}
{!result.isAppropriate && (
<Alert className="border-cyan-500/30 bg-cyan-900/20">
<Lightbulb className="h-4 w-4 text-cyan-400" />
<AlertDescription className="text-cyan-100 text-sm">
使
</AlertDescription>
</Alert>
)}
</CardContent>
</Card>
)
}