feat(connection): 支持生产保护默认折叠

- 为连接配置分区卡片增加可折叠渲染能力

- 生产连接保护默认收起,仅保留标题说明和当前策略标签

- 补充中英文折叠态与展开态回归测试
This commit is contained in:
Syngnat
2026-07-02 14:12:47 +08:00
parent ffb4d16950
commit 69d9f41085
3 changed files with 89 additions and 5 deletions

View File

@@ -162,6 +162,8 @@ vi.mock("@ant-design/icons", () => {
GatewayOutlined: Icon,
SafetyCertificateOutlined: Icon,
ThunderboltOutlined: Icon,
DownOutlined: Icon,
RightOutlined: Icon,
};
});
@@ -526,7 +528,24 @@ describe("ConnectionModal i18n", () => {
findClickableCard(renderer!, sourceLabel).props.onClick();
});
const pageText = textContent(renderer!.toJSON());
let pageText = textContent(renderer!.toJSON());
expect(pageText).toContain(expectations[0]);
expect(pageText).toContain(
language === "zh-CN" ? "未限制" : "No restrictions",
);
expect(pageText).not.toContain(expectations[1]);
expect(pageText).not.toContain(expectations[2]);
const protectionToggle = renderer!.root.findAll(
(node) => node.props?.["data-connection-config-section-toggle"] === "readOnly",
)[0];
expect(protectionToggle.props["aria-expanded"]).toBe(false);
await act(async () => {
protectionToggle.props.onClick({ stopPropagation: vi.fn() });
});
pageText = textContent(renderer!.toJSON());
expectations.forEach((expected) => {
expect(pageText).toContain(expected);
});

View File

@@ -34,6 +34,8 @@ import {
GatewayOutlined,
SafetyCertificateOutlined,
ThunderboltOutlined,
DownOutlined,
RightOutlined,
} from "@ant-design/icons";
import {
getDbIcon,
@@ -693,14 +695,21 @@ const ConnectionModal: React.FC<{
title: string,
description: string,
badge?: React.ReactNode,
options?: {
cursor?: React.CSSProperties["cursor"];
marginBottom?: number;
onClick?: () => void;
},
) => (
<div
onClick={options?.onClick}
style={{
display: "flex",
alignItems: "flex-start",
justifyContent: "space-between",
gap: 12,
marginBottom: 14,
marginBottom: options?.marginBottom ?? 14,
cursor: options?.cursor,
}}
>
<div style={{ display: "flex", alignItems: "flex-start", gap: 10 }}>
@@ -758,20 +767,65 @@ const ConnectionModal: React.FC<{
icon,
children,
badge,
collapsible,
expanded = true,
onToggle,
}: {
sectionKey: ConnectionConfigSectionKey;
icon: React.ReactNode;
children: React.ReactNode;
badge?: React.ReactNode;
collapsible?: boolean;
expanded?: boolean;
onToggle?: () => void;
}) => {
const copy = getConnectionConfigSectionCopy(sectionKey);
const showChildren = !collapsible || expanded;
const resolvedBadge = collapsible ? (
<Space size={8}>
{badge}
<Button
type="text"
size="small"
aria-label={copy.title}
aria-expanded={expanded}
data-connection-config-section-toggle={sectionKey}
onClick={(event) => {
event.stopPropagation();
onToggle?.();
}}
style={{
width: 26,
height: 26,
minWidth: 26,
padding: 0,
borderRadius: 8,
color: overlayTheme.mutedText,
}}
>
{expanded ? <DownOutlined /> : <RightOutlined />}
</Button>
</Space>
) : badge;
return (
<div
data-connection-config-section={sectionKey}
style={configSectionCardStyle()}
>
{renderJvmSectionHeader(icon, copy.title, copy.description, badge)}
{children}
{renderJvmSectionHeader(
icon,
copy.title,
copy.description,
resolvedBadge,
collapsible
? {
cursor: "pointer",
marginBottom: showChildren ? 14 : 0,
onClick: onToggle,
}
: undefined,
)}
{showChildren ? children : null}
</div>
);
};

View File

@@ -194,7 +194,14 @@ const ConnectionModalStep2: React.FC<ConnectionModalStep2Props> = (props) => {
useSSL,
} = props;
const renderStep2 = () => {
const [readOnlyProtectionExpanded, setReadOnlyProtectionExpanded] =
React.useState(false);
React.useEffect(() => {
setReadOnlyProtectionExpanded(false);
}, [dbType]);
const renderStep2 = () => {
const showConnectionReadOnlyField = supportsConnectionReadOnlyMode({
type: dbType,
driver: form.getFieldValue("driver"),
@@ -1364,6 +1371,10 @@ const renderStep2 = () => {
renderConfigSectionCard({
sectionKey: "readOnly",
icon: <SafetyCertificateOutlined />,
collapsible: true,
expanded: readOnlyProtectionExpanded,
onToggle: () =>
setReadOnlyProtectionExpanded((expanded) => !expanded),
badge: (
<Tag
color={