fix: 权限策略弹窗输入框失焦 — FormModal从内联函数组件改为直接JSX内联,避免state更新导致DOM重建

This commit is contained in:
logan committed 2026-05-27 21:42:40 +08:00
1 parent 7f6a4bb6df
commit b5739ba955
1 file changed
+51 -57
+51 -57
View File
@@ -254,61 +254,10 @@ export default function InstanceGroupPage() {
);
};
/* ── Form Modal (shared by create & edit) ── */
const FormModal = ({ mode }: { mode: 'create' | 'edit' }) => {
const show = mode === 'create' ? showCreateModal : showEditModal;
const close = () => { setShowCreateModal(false); setShowEditModal(false); resetForm(); };
const submit = mode === 'create' ? handleCreate : handleEdit;
return show ? (
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[5vh] bg-black/60 backdrop-blur-sm">
<div className="w-full max-w-3xl bg-[var(--dg-bg-primary)] rounded-xl shadow-2xl flex flex-col max-h-[90vh] border border-[var(--dg-border)]" onClick={e => e.stopPropagation()}>
<div className="flex items-center justify-between px-6 py-4 border-b border-[var(--dg-border)]">
<h3 className="text-lg font-semibold">{mode === 'create' ? '新建权限策略' : '编辑权限策略'}</h3>
<button onClick={close} className="p-1.5 rounded-lg hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><X className="w-4 h-4" /></button>
</div>
<div className="overflow-y-auto px-6 py-5 space-y-5 flex-1">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1.5">策略名称 <span className="text-red-400">*</span></label>
<input className="w-full px-3 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-lg text-sm focus:border-blue-400 focus:outline-none" value={formName} onChange={e => setFormName(e.target.value)} placeholder="如:生产数据库权限" />
</div>
<div>
<label className="block text-sm font-medium mb-1.5">描述</label>
<input className="w-full px-3 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-lg text-sm focus:border-blue-400 focus:outline-none" value={formDesc} onChange={e => setFormDesc(e.target.value)} placeholder="可选" />
</div>
</div>
{/* Readonly Transfer */}
<div className="rounded-xl p-4 bg-emerald-500/5 border border-emerald-500/20">
<div className="flex items-center gap-2 mb-3">
<Eye className="w-4 h-4 text-emerald-400" />
<span className="text-sm font-medium text-emerald-400">查询授权</span>
<span className="text-xs text-[var(--dg-text-muted)]">— 查询数据的实例</span>
</div>
<Transfer title="只读实例" items={readonlyTransferItems} selected={readonlyIds} onChange={setReadonlyIds} emptyText="选择用于查询的实例" />
</div>
{/* Write Transfer */}
<div className="rounded-xl p-4 bg-amber-500/5 border border-amber-500/20">
<div className="flex items-center gap-2 mb-3">
<PenLine className="w-4 h-4 text-amber-400" />
<span className="text-sm font-medium text-amber-400">变更授权</span>
<span className="text-xs text-[var(--dg-text-muted)]">— 数据变更工单的实例</span>
</div>
<Transfer title="写入实例" items={writeTransferItems} selected={writeIds} onChange={setWriteIds} emptyText="选择用于变更的实例" />
</div>
<div className="flex justify-end gap-3 pt-2">
<button onClick={close} className="px-4 py-2 text-sm text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)] transition-colors rounded-lg hover:bg-[var(--dg-bg-hover)]">取消</button>
<button onClick={submit} disabled={!formName.trim()} className="dg-btn dg-btn-primary disabled:opacity-50">
{mode === 'create' ? '创建' : '保存'}
</button>
</div>
</div>
</div>
</div>
) : null;
};
/* ── Form Modal shared close/submit ── */
const formClose = () => { setShowCreateModal(false); setShowEditModal(false); resetForm(); };
const formMode = showCreateModal ? 'create' as const : showEditModal ? 'edit' as const : null;
const formSubmit = formMode === 'create' ? handleCreate : handleEdit;
return (
<div className="space-y-5">
@@ -439,8 +388,53 @@ export default function InstanceGroupPage() {
</div>
{/* Form Modal (create & edit) */}
<FormModal mode="create" />
<FormModal mode="edit" />
{formMode && (
<div className="fixed inset-0 z-[100] flex items-start justify-center pt-[5vh] bg-black/60 backdrop-blur-sm">
<div className="w-full max-w-3xl bg-[var(--dg-bg-primary)] rounded-xl shadow-2xl flex flex-col max-h-[90vh] border border-[var(--dg-border)]" onClick={e => e.stopPropagation()}>
<div className="flex items-center justify-between px-6 py-4 border-b border-[var(--dg-border)]">
<h3 className="text-lg font-semibold">{formMode === 'create' ? '新建权限策略' : '编辑权限策略'}</h3>
<button onClick={formClose} className="p-1.5 rounded-lg hover:bg-[var(--dg-bg-hover)] text-[var(--dg-text-muted)] hover:text-[var(--dg-text-primary)] transition-colors"><X className="w-4 h-4" /></button>
</div>
<div className="overflow-y-auto px-6 py-5 space-y-5 flex-1">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium mb-1.5">策略名称 <span className="text-red-400">*</span></label>
<input className="w-full px-3 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-lg text-sm focus:border-blue-400 focus:outline-none" value={formName} onChange={e => setFormName(e.target.value)} placeholder="如:生产数据库权限" />
</div>
<div>
<label className="block text-sm font-medium mb-1.5">描述</label>
<input className="w-full px-3 py-2 bg-[var(--dg-bg-tertiary)] border border-[var(--dg-border)] rounded-lg text-sm focus:border-blue-400 focus:outline-none" value={formDesc} onChange={e => setFormDesc(e.target.value)} placeholder="可选" />
</div>
</div>
<div className="rounded-xl p-4 bg-emerald-500/5 border border-emerald-500/20">
<div className="flex items-center gap-2 mb-3">
<Eye className="w-4 h-4 text-emerald-400" />
<span className="text-sm font-medium text-emerald-400">查询授权</span>
<span className="text-xs text-[var(--dg-text-muted)]">— 查询数据的实例</span>
</div>
<Transfer title="只读实例" items={readonlyTransferItems} selected={readonlyIds} onChange={setReadonlyIds} emptyText="选择用于查询的实例" />
</div>
<div className="rounded-xl p-4 bg-amber-500/5 border border-amber-500/20">
<div className="flex items-center gap-2 mb-3">
<PenLine className="w-4 h-4 text-amber-400" />
<span className="text-sm font-medium text-amber-400">变更授权</span>
<span className="text-xs text-[var(--dg-text-muted)]">— 数据变更工单的实例</span>
</div>
<Transfer title="写入实例" items={writeTransferItems} selected={writeIds} onChange={setWriteIds} emptyText="选择用于变更的实例" />
</div>
<div className="flex justify-end gap-3 pt-2">
<button onClick={formClose} className="px-4 py-2 text-sm text-[var(--dg-text-secondary)] hover:text-[var(--dg-text-primary)] transition-colors rounded-lg hover:bg-[var(--dg-bg-hover)]">取消</button>
<button onClick={formSubmit} disabled={!formName.trim()} className="dg-btn dg-btn-primary disabled:opacity-50">
{formMode === 'create' ? '创建' : '保存'}
</button>
</div>
</div>
</div>
</div>
)}
<ConfirmDialog
open={!!deleteConfirm}