feat: 服务器导入弹窗主题化——CloudServerImport+ExcelServerImport全量替换硬编码slate色为CSS变量+补DialogDescription消除Radix警告

This commit is contained in:
attacker committed 2026-06-15 07:05:02 +08:00
1 parent bc7323e687
commit c111be7610
2 files changed
+113 -111

No files matched your search

@@ -4,15 +4,15 @@ import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import {
Dialog,
DialogContent,
DialogHeader,
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from '@/components/ui/dialog';
import {
import {
Download,
Upload,
FileSpreadsheet,
@@ -271,7 +271,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
return (
<Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="max-w-3xl bg-slate-900 border-slate-700 text-slate-100">
<DialogContent className="max-w-3xl bg-[var(--dg-bg-primary)] border-[var(--dg-border)] text-[var(--dg-text-primary)]">
<DialogHeader>
<DialogTitle className="text-xl">Excel导入服务器</DialogTitle>
<DialogDescription className="sr-only">通过 CSV 文件批量导入服务器资产</DialogDescription>
@@ -282,19 +282,19 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{steps.map((s, index) => (
<div key={s.id} className="flex items-center">
<div className={`flex items-center justify-center w-8 h-8 rounded-full ${
step === s.id
? 'bg-blue-600 text-white'
: step > s.id
? 'bg-emerald-600 text-white'
: 'bg-slate-800 text-slate-500'
step === s.id
? 'bg-blue-600 text-white'
: step > s.id
? 'bg-emerald-600 text-white'
: 'bg-[var(--dg-bg-secondary)] text-[var(--dg-text-muted)]'
}`}>
{step > s.id ? <Check className="h-4 w-4" /> : s.id}
</div>
<span className={`ml-2 text-sm ${step === s.id ? 'text-slate-200' : 'text-slate-500'}`}>
<span className={`ml-2 text-sm ${step === s.id ? 'text-[var(--dg-text-primary)]' : 'text-[var(--dg-text-muted)]'}`}>
{s.title}
</span>
{index < steps.length - 1 && (
<div className="w-12 h-0.5 bg-slate-700 mx-3" />
<div className="w-12 h-0.5 bg-[var(--dg-border)] mx-3" />
)}
</div>
))}
@@ -304,7 +304,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{step === 1 && (
<div className="space-y-6">
{/* Download Template */}
<Card className="bg-slate-800 border-slate-700">
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
<CardContent className="p-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
@@ -312,11 +312,11 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
<FileSpreadsheet className="h-5 w-5 text-emerald-400" />
</div>
<div>
<p className="font-medium text-slate-200">主机导入模板</p>
<p className="text-xs text-slate-500">下载Excel模板,填写服务器信息后上传</p>
<p className="font-medium text-[var(--dg-text-primary)]">主机导入模板</p>
<p className="text-xs text-[var(--dg-text-muted)]">下载Excel模板,填写服务器信息后上传</p>
</div>
</div>
<Button variant="outline" className="border-slate-700 text-slate-300" onClick={downloadTemplate}>
<Button variant="outline" className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]" onClick={downloadTemplate}>
<Download className="h-4 w-4 mr-2" />
下载模板
</Button>
@@ -326,11 +326,11 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{/* Region Selection */}
<div>
<label className="block text-sm font-medium text-slate-300 mb-2">选择区域</label>
<label className="block text-sm font-medium text-[var(--dg-text-secondary)] mb-2">选择区域</label>
<select
value={selectedRegion}
onChange={(e) => setSelectedRegion(e.target.value)}
className="w-full px-3 py-2 bg-slate-800 border border-slate-700 rounded-md text-slate-100 text-sm"
className="w-full px-3 py-2 bg-[var(--dg-bg-secondary)] border border-[var(--dg-border)] rounded-md text-[var(--dg-text-primary)] text-sm"
>
<option value="">请选择区域</option>
{regions.map((region) => (
@@ -343,21 +343,21 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{/* Connection Method */}
<div>
<label className="block text-sm font-medium text-slate-300 mb-2">连接方式</label>
<label className="block text-sm font-medium text-[var(--dg-text-secondary)] mb-2">连接方式</label>
<div className="grid grid-cols-2 gap-4">
{connectionMethods.map((method) => (
<Card
key={method.id}
className={`cursor-pointer transition-all ${
connectionMethod === method.id
? 'border-blue-500 ring-1 ring-blue-500/30 bg-slate-800'
: 'border-slate-700 hover:border-slate-600 bg-slate-800/50'
? 'border-blue-500 ring-1 ring-blue-500/30 bg-[var(--dg-bg-secondary)]'
: 'border-[var(--dg-border)] hover:border-blue-500 bg-[var(--dg-bg-secondary)]'
}`}
onClick={() => setConnectionMethod(method.id)}
>
<CardContent className="p-3">
<p className="font-medium text-slate-200">{method.name}</p>
<p className="text-xs text-slate-500">{method.description}</p>
<p className="font-medium text-[var(--dg-text-primary)]">{method.name}</p>
<p className="text-xs text-[var(--dg-text-muted)]">{method.description}</p>
</CardContent>
</Card>
))}
@@ -369,12 +369,12 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{/* Step 2: Upload */}
{step === 2 && (
<div className="space-y-6">
<div
className="border-2 border-dashed border-slate-700 rounded-lg p-8 text-center hover:border-blue-500/50 transition-colors"
<div
className="border-2 border-dashed border-[var(--dg-border)] rounded-lg p-8 text-center hover:border-blue-500/50 transition-colors"
>
<Upload className="h-12 w-12 mx-auto mb-4 text-slate-500" />
<p className="text-slate-300 mb-2">点击或拖拽文件到此处上传</p>
<p className="text-xs text-slate-500 mb-4">支持 CSV 格式文件(可点击左侧"下载模板"获取)</p>
<Upload className="h-12 w-12 mx-auto mb-4 text-[var(--dg-text-muted)]" />
<p className="text-[var(--dg-text-secondary)] mb-2">点击或拖拽文件到此处上传</p>
<p className="text-xs text-[var(--dg-text-muted)] mb-4">支持 CSV 格式文件(可点击左侧"下载模板"获取)</p>
<Input
type="file"
accept=".csv,text/csv"
@@ -383,26 +383,26 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
id="excel-upload"
/>
<label htmlFor="excel-upload">
<Button variant="outline" className="border-slate-700 text-slate-300" asChild>
<Button variant="outline" className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]" asChild>
<span>选择文件</span>
</Button>
</label>
</div>
{selectedFile && (
<Card className="bg-slate-800 border-slate-700">
<Card className="bg-[var(--dg-bg-secondary)] border-[var(--dg-border)]">
<CardContent className="p-3 flex items-center justify-between">
<div className="flex items-center gap-3">
<FileSpreadsheet className="h-8 w-8 text-emerald-400" />
<div>
<p className="text-sm text-slate-200">{selectedFile.name}</p>
<p className="text-xs text-slate-500">{(selectedFile.size / 1024).toFixed(2)} KB</p>
<p className="text-sm text-[var(--dg-text-primary)]">{selectedFile.name}</p>
<p className="text-xs text-[var(--dg-text-muted)]">{(selectedFile.size / 1024).toFixed(2)} KB</p>
</div>
</div>
<Button
variant="ghost"
size="icon"
className="text-slate-400 hover:text-red-400"
<Button
variant="ghost"
size="icon"
className="text-[var(--dg-text-muted)] hover:text-red-400"
onClick={() => setSelectedFile(null)}
>
<X className="h-4 w-4" />
@@ -414,7 +414,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{isUploading && (
<div className="text-center py-4">
<div className="w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-2" />
<p className="text-slate-400 text-sm">正在解析文件...</p>
<p className="text-[var(--dg-text-secondary)] text-sm">正在解析文件...</p>
</div>
)}
</div>
@@ -424,7 +424,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
{step === 3 && (
<div className="space-y-4">
<div className="flex items-center justify-between">
<p className="text-slate-400 text-sm">数据预览</p>
<p className="text-[var(--dg-text-secondary)] text-sm">数据预览</p>
<div className="flex items-center gap-2">
<Badge className="bg-emerald-500/20 text-emerald-400 border-0">
<Check className="h-3 w-3 mr-1" />
@@ -445,26 +445,26 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
</div>
</div>
<div className="border rounded-lg border-slate-700 overflow-hidden max-h-[350px] overflow-y-auto">
<div className="border rounded-lg border-[var(--dg-border)] overflow-hidden max-h-[350px] overflow-y-auto">
<table className="w-full">
<thead className="bg-slate-800 sticky top-0">
<thead className="bg-[var(--dg-bg-secondary)] sticky top-0">
<tr>
<th className="px-3 py-2 text-left text-xs font-medium text-slate-400">行号</th>
<th className="px-3 py-2 text-left text-xs font-medium text-slate-400">主机名</th>
<th className="px-3 py-2 text-left text-xs font-medium text-slate-400">IP地址</th>
<th className="px-3 py-2 text-left text-xs font-medium text-slate-400">端口</th>
<th className="px-3 py-2 text-left text-xs font-medium text-slate-400">用户名</th>
<th className="px-3 py-2 text-left text-xs font-medium text-slate-400">状态</th>
<th className="px-3 py-2 text-left text-xs font-medium text-[var(--dg-text-secondary)]">行号</th>
<th className="px-3 py-2 text-left text-xs font-medium text-[var(--dg-text-secondary)]">主机名</th>
<th className="px-3 py-2 text-left text-xs font-medium text-[var(--dg-text-secondary)]">IP地址</th>
<th className="px-3 py-2 text-left text-xs font-medium text-[var(--dg-text-secondary)]">端口</th>
<th className="px-3 py-2 text-left text-xs font-medium text-[var(--dg-text-secondary)]">用户名</th>
<th className="px-3 py-2 text-left text-xs font-medium text-[var(--dg-text-secondary)]">状态</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-800">
<tbody className="divide-y divide-[var(--dg-border)]">
{previewData.map((row) => (
<tr key={row.row} className="hover:bg-slate-800/50">
<td className="px-3 py-2 text-sm text-slate-500">{row.row}</td>
<td className="px-3 py-2 text-sm text-slate-200">{row.hostname || '-'}</td>
<td className="px-3 py-2 text-sm text-slate-300">{row.ip}</td>
<td className="px-3 py-2 text-sm text-slate-300">{row.port}</td>
<td className="px-3 py-2 text-sm text-slate-300">{row.username}</td>
<tr key={row.row} className="hover:bg-[var(--dg-bg-hover)]">
<td className="px-3 py-2 text-sm text-[var(--dg-text-muted)]">{row.row}</td>
<td className="px-3 py-2 text-sm text-[var(--dg-text-primary)]">{row.hostname || '-'}</td>
<td className="px-3 py-2 text-sm text-[var(--dg-text-secondary)]">{row.ip}</td>
<td className="px-3 py-2 text-sm text-[var(--dg-text-secondary)]">{row.port}</td>
<td className="px-3 py-2 text-sm text-[var(--dg-text-secondary)]">{row.username}</td>
<td className="px-3 py-2">
<div className="flex items-center gap-1">
{row.status === 'valid' && (
@@ -508,19 +508,19 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
<DialogFooter className="flex justify-between items-center">
<div>
{step > 1 && (
<Button variant="outline" onClick={handleBack} className="border-slate-700 text-slate-300">
<Button variant="outline" onClick={handleBack} className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]">
<ChevronLeft className="h-4 w-4 mr-1" />
上一步
</Button>
)}
</div>
<div className="flex gap-2">
<Button variant="outline" onClick={handleClose} className="border-slate-700 text-slate-300">
<Button variant="outline" onClick={handleClose} className="border-[var(--dg-border)] text-[var(--dg-text-secondary)]">
取消
</Button>
{step < 3 ? (
<Button
onClick={handleNext}
<Button
onClick={handleNext}
disabled={(step === 1 && !selectedRegion) || (step === 2 && !selectedFile)}
className="bg-blue-600 hover:bg-blue-700"
>
@@ -528,7 +528,7 @@ export function ExcelServerImport({ open, onClose }: ExcelServerImportProps) {
<ChevronRight className="h-4 w-4 ml-1" />
</Button>
) : (
<Button
<Button
onClick={handleImport}
disabled={isImporting || errorCount > 0 || validCount === 0}
className="bg-emerald-600 hover:bg-emerald-700"