- CronJobManager: 编辑按钮接通 onClick → openEdit(job),弹出编辑对话框预填数据,
复用新建/编辑共用 Dialog(editingId 区分模式),标题/按钮文案动态切换,
保存时根据 editingId 调用 createJob 或 updateJob — 消除占位按钮
- ApprovalFlow: 修复 API 方法名不匹配导致 tsc -b 编译失败
(getInstances→getProcesses, getMyApprovals→getProcesses({status:'pending'}),
approveInstance→approveProcess, rejectInstance→rejectProcess)
+ 添加 ApprovalFlowManager 导出别名兼容 App.tsx 导入
- 合并已完成的大文件拆分重构: automation.go→automation_cron/script/playbook,
ldap.go→ldap_ou/ldap_users, server.go→cloud_accounts/domain/platform/region,
user.go→user_admin; 前端 Dashboard/K8s/Server/Approval/Monitor 子组件拆分
// Logan.Li
73 lines
2.9 KiB
TypeScript
73 lines
2.9 KiB
TypeScript
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Plus, Shield, Edit, Eye } from 'lucide-react';
|
|
import { roles } from '@/mocks/data';
|
|
import type { Role } from '@/types';
|
|
|
|
interface SystemRolesTabProps {
|
|
selectedRole: Role | null;
|
|
setSelectedRole: (role: Role | null) => void;
|
|
}
|
|
|
|
export function SystemRolesTab({ selectedRole, setSelectedRole }: SystemRolesTabProps) {
|
|
return (
|
|
<>
|
|
<div className="flex items-center justify-end">
|
|
<Button className="bg-blue-600 hover:bg-blue-700 text-white">
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
新建角色
|
|
</Button>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
{roles.map((role) => (
|
|
<Card key={role.id} className="bg-slate-900 border-slate-800">
|
|
<CardHeader className="pb-2">
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-10 h-10 rounded-lg bg-purple-500/10 flex items-center justify-center">
|
|
<Shield className="h-5 w-5 text-purple-400" />
|
|
</div>
|
|
<div>
|
|
<CardTitle className="text-base text-slate-100">{role.name}</CardTitle>
|
|
<CardDescription className="text-slate-500">{role.code}</CardDescription>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-1">
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
className="h-8 w-8 text-slate-400 hover:text-slate-100"
|
|
onClick={() => setSelectedRole(role)}
|
|
>
|
|
<Eye className="h-4 w-4" />
|
|
</Button>
|
|
<Button variant="ghost" size="icon" className="h-8 w-8 text-slate-400 hover:text-slate-100">
|
|
<Edit className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="text-sm text-slate-400 mb-3">{role.description}</p>
|
|
<div className="flex flex-wrap gap-1">
|
|
{role.permissions.slice(0, 5).map((permission) => (
|
|
<Badge key={permission} variant="outline" className="border-slate-700 text-slate-400 text-xs">
|
|
{permission}
|
|
</Badge>
|
|
))}
|
|
{role.permissions.length > 5 && (
|
|
<Badge variant="outline" className="border-slate-700 text-slate-400 text-xs">
|
|
+{role.permissions.length - 5}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|