"use client" import { Textarea } from "@/components/ui/textarea" import { useState } from "react" import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Switch } from "@/components/ui/switch" import { Badge } from "@/components/ui/badge" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Separator } from "@/components/ui/separator" import { AlertTriangle, CheckCircle, Bell, RefreshCw, Filter, Download, Search, Clock } from "lucide-react" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" interface DataQualityIssue { id: string type: string description: string affectedRecords: number affectedFields: string[] severity: "high" | "medium" | "low" status: "open" | "in_progress" | "resolved" createdAt: string dataSource: string } interface DataQualityRule { id: string name: string description: string type: string enabled: boolean severity: "high" | "medium" | "low" dataSource: string lastRun: string issuesDetected: number } export function DataQualityMonitor() { const [activeTab, setActiveTab] = useState("issues") const [selectedIssueId, setSelectedIssueId] = useState(null) const [isAddingRule, setIsAddingRule] = useState(false) const [filterSeverity, setFilterSeverity] = useState("all") const [filterStatus, setFilterStatus] = useState("all") // 模拟数据质量问题 const [dataQualityIssues, setDataQualityIssues] = useState([ { id: "issue-1", type: "缺失值", description: "用户表中存在大量手机号字段为空的记录", affectedRecords: 1250, affectedFields: ["phoneNumber"], severity: "high", status: "open", createdAt: "2023-07-20 10:15", dataSource: "CRM系统", }, { id: "issue-2", type: "格式错误", description: "部分用户的身份证号格式不正确", affectedRecords: 458, affectedFields: ["identityNumber"], severity: "medium", status: "in_progress", createdAt: "2023-07-19 15:30", dataSource: "用户数据库", }, { id: "issue-3", type: "重复数据", description: "存在多条使用相同手机号的用户记录", affectedRecords: 789, affectedFields: ["userId", "phoneNumber"], severity: "medium", status: "open", createdAt: "2023-07-18 09:45", dataSource: "交易系统", }, { id: "issue-4", type: "异常值", description: "部分用户的年龄字段值异常(超过150岁)", affectedRecords: 23, affectedFields: ["age"], severity: "low", status: "resolved", createdAt: "2023-07-17 14:20", dataSource: "用户数据库", }, { id: "issue-5", type: "不一致数据", description: "用户在不同系统中的姓名不一致", affectedRecords: 567, affectedFields: ["fullName"], severity: "high", status: "open", createdAt: "2023-07-16 11:05", dataSource: "多系统", }, ]) // 模拟数据质量规则 const [dataQualityRules, setDataQualityRules] = useState([ { id: "rule-1", name: "手机号格式检查", description: "检查手机号是否符合中国大陆手机号格式", type: "格式验证", enabled: true, severity: "high", dataSource: "所有数据源", lastRun: "2023-07-20 00:00", issuesDetected: 458, }, { id: "rule-2", name: "身份证号验证", description: "验证身份证号的格式和校验码", type: "格式验证", enabled: true, severity: "high", dataSource: "所有数据源", lastRun: "2023-07-20 00:00", issuesDetected: 789, }, { id: "rule-3", name: "必填字段检查", description: "检查关键字段是否有值", type: "完整性检查", enabled: true, severity: "medium", dataSource: "所有数据源", lastRun: "2023-07-20 00:00", issuesDetected: 1250, }, { id: "rule-4", name: "重复数据检测", description: "检测并标记重复的用户记录", type: "唯一性检查", enabled: true, severity: "medium", dataSource: "所有数据源", lastRun: "2023-07-20 00:00", issuesDetected: 567, }, { id: "rule-5", name: "数据一致性检查", description: "检查用户在不同系统中的数据是否一致", type: "一致性检查", enabled: true, severity: "high", dataSource: "所有数据源", lastRun: "2023-07-20 00:00", issuesDetected: 567, }, ]) // 模拟数据质量统计 const qualityStats = { totalIssues: 3087, openIssues: 2606, resolvedIssues: 481, highSeverity: 1245, mediumSeverity: 1356, lowSeverity: 486, dataQualityScore: 87, completenessScore: 92, accuracyScore: 85, consistencyScore: 88, validityScore: 84, } const getSeverityBadge = (severity: string) => { switch (severity) { case "high": return case "medium": return case "low": return default: return 未知 } } const getStatusBadge = (status: string) => { switch (status) { case "open": return 未解决 case "in_progress": return 处理中 case "resolved": return 已解决 default: return 未知 } } const getStatusIcon = (status: string) => { switch (status) { case "open": return case "in_progress": return case "resolved": return default: return } } const filteredIssues = dataQualityIssues.filter((issue) => { if (filterSeverity !== "all" && issue.severity !== filterSeverity) return false if (filterStatus !== "all" && issue.status !== filterStatus) return false return true }) const selectedIssue = selectedIssueId ? dataQualityIssues.find((issue) => issue.id === selectedIssueId) : null const updateIssueStatus = (id: string, status: "open" | "in_progress" | "resolved") => { setDataQualityIssues( dataQualityIssues.map((issue) => { if (issue.id === id) { return { ...issue, status } } return issue }), ) } const toggleRuleStatus = (id: string) => { setDataQualityRules( dataQualityRules.map((rule) => { if (rule.id === id) { return { ...rule, enabled: !rule.enabled } } return rule }), ) } return (

数据质量监控

数据质量评分

{qualityStats.dataQualityScore}/100

未解决问题

{qualityStats.openIssues}

其中高严重性: {qualityStats.highSeverity} 个问题

处理中问题

{dataQualityIssues.filter((issue) => issue.status === "in_progress").length}

正在处理中的数据质量问题

已解决问题

{qualityStats.resolvedIssues}

解决率: {((qualityStats.resolvedIssues / qualityStats.totalIssues) * 100).toFixed(1)}%

数据问题 质量规则 质量指标 质量报告
数据质量问题
状态 问题类型 描述 影响记录数 严重性 数据源 发现时间 操作 {filteredIssues.map((issue) => ( {getStatusIcon(issue.status)} {issue.type} {issue.description} {issue.affectedRecords.toLocaleString()} {getSeverityBadge(issue.severity)} {issue.dataSource} {issue.createdAt} ))}
数据质量规则
规则名称 类型 严重性 数据源 上次运行 检测到的问题 状态 操作 {dataQualityRules.map((rule) => ( {rule.name} {rule.type} {getSeverityBadge(rule.severity)} {rule.dataSource} {rule.lastRun} {rule.issuesDetected.toLocaleString()}
toggleRuleStatus(rule.id)} aria-label="Toggle rule" /> {rule.enabled ? "启用" : "禁用"}
))}
数据完整性 数据字段的完整性评分
总体完整性评分 {qualityStats.completenessScore}/100

关键字段完整性

用户ID 100%
手机号 87%
身份证号 72%
IMEI设备号 68%
数据准确性 数据值的准确性评分
总体准确性评分 {qualityStats.accuracyScore}/100

字段准确性

手机号格式 92%
身份证号格式 85%
年龄范围 95%
邮箱格式 78%
数据一致性 跨系统数据一致性评分
总体一致性评分 {qualityStats.consistencyScore}/100

系统间一致性

CRM与交易系统 90%
用户数据库与行为分析 85%
交易系统与设备管理 78%
数据有效性 数据业务规则有效性评分
总体有效性评分 {qualityStats.validityScore}/100

业务规则有效性

用户注册规则 92%
交易记录规则 88%
用户行为规则 75%
数据质量报告
报告名称 生成时间 质量评分 问题数量 严重问题 操作 每周数据质量报告 2023-07-21 87/100 156 23 每周数据质量报告 2023-07-14 85/100 178 31 每周数据质量报告 2023-07-07 82/100 203 45 每月数据质量报告 2023-06-30 80/100 245 52
{/* 问题详情对话框 */} !open && setSelectedIssueId(null)}> 问题详情 查看和处理数据质量问题 {selectedIssue && (
{getStatusIcon(selectedIssue.status)}

{selectedIssue.type}

{selectedIssue.description}

{getSeverityBadge(selectedIssue.severity)}

{getStatusBadge(selectedIssue.status)}

{selectedIssue.dataSource}

{selectedIssue.createdAt}

{selectedIssue.affectedRecords.toLocaleString()}

{selectedIssue.affectedFields.map((field, index) => ( {field} ))}