Reorganize navigation and module structure based on new requirements. Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
224 lines
8.7 KiB
TypeScript
224 lines
8.7 KiB
TypeScript
"use client"
|
||
|
||
import { useState } from "react"
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
} from "@/components/ui/dialog"
|
||
import { Button } from "@/components/ui/button"
|
||
import { Input } from "@/components/ui/input"
|
||
import { Label } from "@/components/ui/label"
|
||
import { Textarea } from "@/components/ui/textarea"
|
||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
||
import { Switch } from "@/components/ui/switch"
|
||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||
import { Settings, Code, Clock, Bell } from "lucide-react"
|
||
|
||
interface CleaningRuleSettingsDialogProps {
|
||
open: boolean
|
||
onOpenChange: (open: boolean) => void
|
||
rule?: {
|
||
id: string
|
||
name: string
|
||
description: string
|
||
type: string
|
||
sourceTable: string
|
||
targetTable: string
|
||
status: string
|
||
}
|
||
}
|
||
|
||
export function CleaningRuleSettingsDialog({ open, onOpenChange, rule }: CleaningRuleSettingsDialogProps) {
|
||
const [activeTab, setActiveTab] = useState("basic")
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||
<DialogContent className="max-w-2xl">
|
||
<DialogHeader>
|
||
<DialogTitle className="flex items-center gap-2">
|
||
<Settings className="w-5 h-5" />
|
||
规则设置 - {rule?.name || "清洗规则"}
|
||
</DialogTitle>
|
||
<DialogDescription>配置清洗规则的执行参数和调度策略</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
<Tabs value={activeTab} onValueChange={setActiveTab}>
|
||
<TabsList className="grid w-full grid-cols-4">
|
||
<TabsTrigger value="basic">基本信息</TabsTrigger>
|
||
<TabsTrigger value="logic">清洗逻辑</TabsTrigger>
|
||
<TabsTrigger value="schedule">调度配置</TabsTrigger>
|
||
<TabsTrigger value="alert">告警设置</TabsTrigger>
|
||
</TabsList>
|
||
|
||
<TabsContent value="basic" className="space-y-4 mt-4">
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label>规则名称</Label>
|
||
<Input defaultValue={rule?.name} />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>规则类型</Label>
|
||
<Select defaultValue={rule?.type}>
|
||
<SelectTrigger>
|
||
<SelectValue />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="format">格式化</SelectItem>
|
||
<SelectItem value="dedup">去重</SelectItem>
|
||
<SelectItem value="mapping">映射</SelectItem>
|
||
<SelectItem value="validate">校验</SelectItem>
|
||
<SelectItem value="transform">转换</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>规则描述</Label>
|
||
<Textarea defaultValue={rule?.description} rows={3} />
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label>源数据表</Label>
|
||
<Input defaultValue={rule?.sourceTable} />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>目标数据表</Label>
|
||
<Input defaultValue={rule?.targetTable} />
|
||
</div>
|
||
</div>
|
||
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
|
||
<div>
|
||
<p className="font-medium">启用规则</p>
|
||
<p className="text-sm text-slate-500">关闭后规则将不再自动执行</p>
|
||
</div>
|
||
<Switch defaultChecked={rule?.status === "active"} />
|
||
</div>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="logic" className="space-y-4 mt-4">
|
||
<div className="space-y-2">
|
||
<Label className="flex items-center gap-2">
|
||
<Code className="w-4 h-4" />
|
||
清洗SQL逻辑
|
||
</Label>
|
||
<div className="bg-slate-900 rounded-lg p-4 font-mono text-sm text-green-400 min-h-[200px]">
|
||
<pre>{`-- 清洗逻辑示例
|
||
SELECT
|
||
user_id,
|
||
TRIM(LOWER(email)) as email,
|
||
REGEXP_REPLACE(phone, '[^0-9]', '') as phone
|
||
FROM ${rule?.sourceTable || "source_table"}
|
||
WHERE email IS NOT NULL;`}</pre>
|
||
</div>
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label>批处理大小</Label>
|
||
<Input type="number" defaultValue="10000" />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>并发线程数</Label>
|
||
<Input type="number" defaultValue="4" />
|
||
</div>
|
||
</div>
|
||
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
|
||
<div>
|
||
<p className="font-medium">增量处理</p>
|
||
<p className="text-sm text-slate-500">仅处理新增或变更的数据</p>
|
||
</div>
|
||
<Switch defaultChecked />
|
||
</div>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="schedule" className="space-y-4 mt-4">
|
||
<div className="space-y-2">
|
||
<Label className="flex items-center gap-2">
|
||
<Clock className="w-4 h-4" />
|
||
调度类型
|
||
</Label>
|
||
<Select defaultValue="cron">
|
||
<SelectTrigger>
|
||
<SelectValue />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="manual">手动执行</SelectItem>
|
||
<SelectItem value="interval">固定间隔</SelectItem>
|
||
<SelectItem value="cron">Cron表达式</SelectItem>
|
||
<SelectItem value="realtime">实时触发</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>Cron表达式</Label>
|
||
<Input defaultValue="0 */1 * * *" placeholder="例: 0 */1 * * * (每小时执行)" />
|
||
<p className="text-xs text-slate-500">当前设置:每小时执行一次</p>
|
||
</div>
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label>超时时间(分钟)</Label>
|
||
<Input type="number" defaultValue="30" />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>重试次数</Label>
|
||
<Input type="number" defaultValue="3" />
|
||
</div>
|
||
</div>
|
||
</TabsContent>
|
||
|
||
<TabsContent value="alert" className="space-y-4 mt-4">
|
||
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
|
||
<div className="flex items-center gap-2">
|
||
<Bell className="w-4 h-4" />
|
||
<div>
|
||
<p className="font-medium">执行失败告警</p>
|
||
<p className="text-sm text-slate-500">规则执行失败时发送通知</p>
|
||
</div>
|
||
</div>
|
||
<Switch defaultChecked />
|
||
</div>
|
||
<div className="flex items-center justify-between p-4 bg-slate-50 rounded-lg">
|
||
<div className="flex items-center gap-2">
|
||
<Bell className="w-4 h-4" />
|
||
<div>
|
||
<p className="font-medium">错误率告警</p>
|
||
<p className="text-sm text-slate-500">错误率超过阈值时发送通知</p>
|
||
</div>
|
||
</div>
|
||
<Switch defaultChecked />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>错误率阈值(%)</Label>
|
||
<Input type="number" defaultValue="5" />
|
||
</div>
|
||
<div className="space-y-2">
|
||
<Label>通知渠道</Label>
|
||
<Select defaultValue="all">
|
||
<SelectTrigger>
|
||
<SelectValue />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="email">邮件</SelectItem>
|
||
<SelectItem value="sms">短信</SelectItem>
|
||
<SelectItem value="webhook">Webhook</SelectItem>
|
||
<SelectItem value="all">全部渠道</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</TabsContent>
|
||
</Tabs>
|
||
|
||
<DialogFooter>
|
||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||
取消
|
||
</Button>
|
||
<Button onClick={() => onOpenChange(false)}>保存设置</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
)
|
||
}
|