feat: 优化响应布局
parent
b06b7585d8
commit
c0b4c0d319
|
|
@ -39,7 +39,7 @@ function ListTable<T extends Record<string, any>>({
|
|||
showSizeChanger: { showSearch: false },
|
||||
showQuickJumper: true,
|
||||
},
|
||||
scroll = { x: "max-content" },
|
||||
scroll = { x: "max(100%, 960px)" },
|
||||
onRowClick,
|
||||
selectedRow,
|
||||
loading = false,
|
||||
|
|
@ -49,7 +49,7 @@ function ListTable<T extends Record<string, any>>({
|
|||
}: ListTableProps<T>) {
|
||||
const mergedScroll = React.useMemo(() => {
|
||||
return {
|
||||
x: "max-content",
|
||||
x: "max(100%, 960px)",
|
||||
...scroll,
|
||||
};
|
||||
}, [scroll]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
.long-text-preview {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.long-text-preview-popover {
|
||||
max-width: min(720px, 70vw);
|
||||
}
|
||||
|
||||
.long-text-preview-popover__content {
|
||||
max-width: min(680px, 66vw);
|
||||
max-height: 360px;
|
||||
margin: 0 !important;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
user-select: text;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.long-text-preview-popover__content--code {
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { Popover, Typography } from "antd";
|
||||
import type { TextProps } from "antd/es/typography/Text";
|
||||
import "./LongTextPreview.css";
|
||||
|
||||
const { Paragraph, Text } = Typography;
|
||||
|
||||
type LongTextPreviewProps = {
|
||||
value?: string | number | null;
|
||||
emptyText?: string;
|
||||
code?: boolean;
|
||||
copyable?: boolean;
|
||||
className?: string;
|
||||
textType?: TextProps["type"];
|
||||
strong?: boolean;
|
||||
};
|
||||
|
||||
export default function LongTextPreview({
|
||||
value,
|
||||
emptyText = "-",
|
||||
code = false,
|
||||
copyable = true,
|
||||
className,
|
||||
textType,
|
||||
strong,
|
||||
}: LongTextPreviewProps) {
|
||||
const text = value === undefined || value === null || value === "" ? emptyText : String(value);
|
||||
const contentClassName = [
|
||||
"long-text-preview-popover__content",
|
||||
code ? "long-text-preview-popover__content--code" : undefined,
|
||||
].filter(Boolean).join(" ");
|
||||
|
||||
return (
|
||||
<Popover
|
||||
overlayClassName="long-text-preview-popover"
|
||||
placement="topLeft"
|
||||
content={
|
||||
<Paragraph className={contentClassName} copyable={copyable ? { text } : false}>
|
||||
{text}
|
||||
</Paragraph>
|
||||
}
|
||||
>
|
||||
<Text code={code} type={textType} strong={strong} className={["long-text-preview", className].filter(Boolean).join(" ")}>
|
||||
{text}
|
||||
</Text>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
@ -88,3 +88,26 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.permissions-route-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.permissions-route-text--component {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.permissions-name-cell {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.permissions-name-cell .ant-space-item:last-child {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.permissions-name-cell .long-text-preview {
|
||||
min-width: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import { usePermission } from "@/hooks/usePermission";
|
|||
import PageContainer from "@/components/shared/PageContainer";
|
||||
import DataListPanel from "@/components/shared/DataListPanel";
|
||||
import SectionCard from "@/components/shared/SectionCard";
|
||||
import LongTextPreview from "@/components/shared/LongTextPreview";
|
||||
import type { SysPermission } from "@/types";
|
||||
import "./index.less";
|
||||
|
||||
|
|
@ -453,18 +454,22 @@ export default function Permissions() {
|
|||
title: t("permissions.permName"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: 360,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (text: string, record: TreePermission) => {
|
||||
let icon = <CheckSquareOutlined style={{ color: "#52c41a" }} aria-hidden="true" />;
|
||||
if (record.permType === "directory") icon = <FolderOutlined style={{ color: "#faad14" }} aria-hidden="true" />;
|
||||
if (record.permType === "menu") icon = <MenuOutlined style={{ color: "#1890ff" }} aria-hidden="true" />;
|
||||
return <Space>{icon}<Text strong={record.level === 1}>{text}</Text></Space>;
|
||||
return <Space className="permissions-name-cell">{icon}<LongTextPreview value={text} strong={record.level === 1} copyable={false} /></Space>;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: t("permissions.permCode"),
|
||||
dataIndex: "code",
|
||||
key: "code",
|
||||
render: (text: string) => text ? <Tag color="blue" className="tabular-nums">{text}</Tag> : "-"
|
||||
width: 220,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (text: string) => text ? <LongTextPreview value={text} code className="tabular-nums" /> : "-"
|
||||
},
|
||||
{
|
||||
title: t("permissions.permType"),
|
||||
|
|
@ -478,15 +483,16 @@ export default function Permissions() {
|
|||
return <Tag color={color}>{item ? item.itemLabel : type}</Tag>;
|
||||
}
|
||||
},
|
||||
{ title: t("permissions.sort"), dataIndex: "sortOrder", width: 80, className: "tabular-nums" },
|
||||
{ title: t("permissions.sort"), dataIndex: "sortOrder", width: 72, className: "tabular-nums" },
|
||||
{
|
||||
title: t("permissions.route"),
|
||||
key: "route",
|
||||
ellipsis: true,
|
||||
width: 220,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (_: unknown, record: TreePermission) => (
|
||||
<div className="flex flex-col">
|
||||
{record.path && <Text type="secondary" style={{ fontSize: "12px" }} className="tabular-nums">{record.path}</Text>}
|
||||
{record.component && <Text type="secondary" style={{ fontSize: "11px" }}>{record.component}</Text>}
|
||||
{record.path && <LongTextPreview value={record.path} textType="secondary" className="tabular-nums permissions-route-text" />}
|
||||
{record.component && <LongTextPreview value={record.component} textType="secondary" className="permissions-route-text permissions-route-text--component" />}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
|
@ -510,7 +516,7 @@ export default function Permissions() {
|
|||
},
|
||||
{
|
||||
title: t("common.action"),
|
||||
width: 150,
|
||||
width: 132,
|
||||
fixed: "right" as const,
|
||||
render: (_: unknown, record: TreePermission) => (
|
||||
<Space>
|
||||
|
|
@ -583,7 +589,8 @@ export default function Permissions() {
|
|||
columns={columns}
|
||||
pagination={false}
|
||||
size="middle"
|
||||
scroll={{ x: 'max-content', y: '100%' }}
|
||||
scroll={{ x: 'max(100%, 1080px)', y: '100%' }}
|
||||
tableLayout="fixed"
|
||||
expandable={{
|
||||
defaultExpandAllRows: false,
|
||||
rowExpandable: (record) => record.permType !== "button" && !!record.children?.length,
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ const AiModels: React.FC = () => {
|
|||
columns={resolvedTableColumns}
|
||||
dataSource={data}
|
||||
loading={loading}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 960px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ export default function ClientManagement() {
|
|||
columns={columns}
|
||||
dataSource={pagedRecords}
|
||||
loading={loading || groupLoading || platformLoading}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 960px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ export default function ExternalAppManagement() {
|
|||
columns={columns}
|
||||
dataSource={pagedRecords}
|
||||
loading={loading}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 1000px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ const HotWords: React.FC = () => {
|
|||
dataSource={data}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 1000px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import DataListPanel from "@/components/shared/DataListPanel";
|
|||
import ListTable from "@/components/shared/ListTable/ListTable";
|
||||
import SectionCard from "@/components/shared/SectionCard";
|
||||
import SummaryStatCards from "@/components/shared/SummaryStatCards";
|
||||
import LongTextPreview from "@/components/shared/LongTextPreview";
|
||||
import { listLicenses, type LicenseVO } from "@/api/business/license";
|
||||
import "./LicenseManagement.css";
|
||||
|
||||
|
|
@ -105,9 +106,10 @@ export default function LicenseManagement() {
|
|||
title: "授权标识",
|
||||
key: "license",
|
||||
width: 320,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (_, record) => (
|
||||
<Space direction="vertical" size={0}>
|
||||
<Text strong className="tabular-nums">{record.licenseSerial}</Text>
|
||||
<Space direction="vertical" size={0} style={{ width: "100%" }}>
|
||||
<LongTextPreview value={record.licenseSerial} strong className="tabular-nums" />
|
||||
{/*<Text type="secondary" className="tabular-nums">{record.licenseCode}</Text>*/}
|
||||
</Space>
|
||||
),
|
||||
|
|
@ -131,7 +133,8 @@ export default function LicenseManagement() {
|
|||
dataIndex: "deviceCode",
|
||||
key: "deviceCode",
|
||||
width: 240,
|
||||
render: (value) => <Text className="tabular-nums">{value || "-"}</Text>,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (value) => <LongTextPreview value={value} className="tabular-nums" />,
|
||||
},
|
||||
{
|
||||
title: "过期时间",
|
||||
|
|
@ -184,7 +187,7 @@ export default function LicenseManagement() {
|
|||
dataSource={pagedRecords}
|
||||
loading={loading}
|
||||
pagination={false}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 960px)", y: "100%" }}
|
||||
/>
|
||||
</DataListPanel>
|
||||
</SectionCard>
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@ export default function MeetingPointsManagement() {
|
|||
columns={overviewColumns}
|
||||
dataSource={overviewRows}
|
||||
loading={false}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 760px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
) : activeTabKey === "personal" ? (
|
||||
|
|
@ -466,7 +466,7 @@ export default function MeetingPointsManagement() {
|
|||
columns={personalAccountColumns}
|
||||
dataSource={pagedPersonalAccounts}
|
||||
loading={false}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 760px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
) : (
|
||||
|
|
@ -476,7 +476,7 @@ export default function MeetingPointsManagement() {
|
|||
columns={ledgerColumns}
|
||||
dataSource={records}
|
||||
loading={loading}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 960px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -923,7 +923,7 @@ const Meetings: React.FC = () => {
|
|||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={false}
|
||||
scroll={{ x: "max-content", y: "calc(100vh - 430px)" }}
|
||||
scroll={{ x: "max(100%, 1180px)", y: "calc(100vh - 430px)" }}
|
||||
onRow={(record) => ({ onClick: () => handleOpenMeeting(record) })}
|
||||
locale={{ emptyText: <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="开启您的第一场会议分析" /> }}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ const PromptTemplates: React.FC = () => {
|
|||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={false}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 1400px)", y: "100%" }}
|
||||
onRow={(record) => ({ onClick: () => showDetail(record) })}
|
||||
locale={{ emptyText: <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无可用模板" /> }}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -798,7 +798,7 @@ export default function ScreenSaverManagement() {
|
|||
locale={{
|
||||
emptyText: <Empty description="暂无屏保素材" />,
|
||||
}}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 1080px)", y: "100%" }}
|
||||
/>
|
||||
</DataListPanel>
|
||||
</SectionCard>
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ const SpeakerReg: React.FC = () => {
|
|||
columns={columns}
|
||||
dataSource={filteredSpeakers}
|
||||
loading={listLoading}
|
||||
scroll={{ x: "max-content", y: "100%" }}
|
||||
scroll={{ x: "max(100%, 960px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ export default function TenantMeetingPointsSettings() {
|
|||
dataSource={records}
|
||||
loading={loading}
|
||||
totalCount={total}
|
||||
scroll={{x: "max-content", y: "100%"}}
|
||||
scroll={{x: "max(100%, 1280px)", y: "100%"}}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { useDict } from "@/hooks/useDict";
|
|||
import { usePermission } from "@/hooks/usePermission";
|
||||
import PageContainer from "@/components/shared/PageContainer";
|
||||
import SectionCard from "@/components/shared/SectionCard";
|
||||
import LongTextPreview from "@/components/shared/LongTextPreview";
|
||||
import type { OrgNode, SysOrg, SysTenant } from "@/types";
|
||||
import "./index.less";
|
||||
|
||||
|
|
@ -130,8 +131,8 @@ export default function Orgs() {
|
|||
};
|
||||
|
||||
const columns = [
|
||||
{ title: t("orgs.orgName"), dataIndex: "orgName", key: "orgName", render: (text: string) => <Text strong>{text}</Text> },
|
||||
{ title: t("orgs.orgCode"), dataIndex: "orgCode", key: "orgCode", width: 150, render: (text: string) => <Tag className="tabular-nums">{text || "-"}</Tag> },
|
||||
{ title: t("orgs.orgName"), dataIndex: "orgName", key: "orgName", width: 320, ellipsis: { showTitle: false }, render: (text: string) => <LongTextPreview value={text} strong /> },
|
||||
{ title: t("orgs.orgCode"), dataIndex: "orgCode", key: "orgCode", width: 180, ellipsis: { showTitle: false }, render: (text: string) => <LongTextPreview value={text} code className="tabular-nums" /> },
|
||||
{ title: t("orgs.sort"), dataIndex: "sortOrder", width: 100, className: "tabular-nums" },
|
||||
{
|
||||
title: t("common.status"),
|
||||
|
|
@ -188,7 +189,7 @@ export default function Orgs() {
|
|||
</div>
|
||||
<div className="orgs-table-shell">
|
||||
{selectedTenantId !== undefined ? (
|
||||
<Table rowKey="id" columns={columns} dataSource={treeData} loading={loading} pagination={false} size="middle" scroll={{ y: "100%" }} expandable={{ defaultExpandAllRows: true }} />
|
||||
<Table rowKey="id" columns={columns} dataSource={treeData} loading={loading} pagination={false} size="middle" scroll={{ x: "max(100%, 920px)", y: "100%" }} tableLayout="fixed" expandable={{ defaultExpandAllRows: true }} />
|
||||
) : (
|
||||
<div className="app-page__empty-state"><Empty description={t("orgs.selectTenant")} /></div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { useDict } from "@/hooks/useDict";
|
|||
import { usePermission } from "@/hooks/usePermission";
|
||||
import PageContainer from "@/components/shared/PageContainer";
|
||||
import SectionCard from "@/components/shared/SectionCard";
|
||||
import LongTextPreview from "@/components/shared/LongTextPreview";
|
||||
import { getStandardPagination } from "@/utils/pagination";
|
||||
import type { SysDictItem, SysDictType } from "@/types";
|
||||
import "./index.less";
|
||||
|
|
@ -243,10 +244,11 @@ export default function Dictionaries() {
|
|||
dataSource={items}
|
||||
pagination={false}
|
||||
size="middle"
|
||||
scroll={{ y: "calc(100vh - 320px)" }}
|
||||
scroll={{ x: "max(100%, 760px)", y: "calc(100vh - 320px)" }}
|
||||
tableLayout="fixed"
|
||||
columns={[
|
||||
{ title: t("dicts.itemLabel"), dataIndex: "itemLabel", render: (text: string) => <Text strong>{text}</Text> },
|
||||
{ title: t("dicts.itemValue"), dataIndex: "itemValue", className: "tabular-nums" },
|
||||
{ title: t("dicts.itemLabel"), dataIndex: "itemLabel", width: 220, ellipsis: { showTitle: false }, render: (text: string) => <LongTextPreview value={text} strong /> },
|
||||
{ title: t("dicts.itemValue"), dataIndex: "itemValue", width: 220, ellipsis: { showTitle: false }, render: (text: string) => <LongTextPreview value={text} code className="tabular-nums" /> },
|
||||
{ title: t("dicts.sort"), dataIndex: "sortOrder", width: 80, className: "tabular-nums" },
|
||||
{
|
||||
title: t("common.status"),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import DataListPanel from "@/components/shared/DataListPanel";
|
|||
import ListTable from "@/components/shared/ListTable/ListTable";
|
||||
import AppPagination from "@/components/shared/AppPagination";
|
||||
import SectionCard from "@/components/shared/SectionCard";
|
||||
import LongTextPreview from "@/components/shared/LongTextPreview";
|
||||
import { getDefaultPageSize } from "@/utils/pagination";
|
||||
import type { SysLog, SysTenant, UserProfile } from "@/types";
|
||||
import "./index.less";
|
||||
|
|
@ -19,7 +20,7 @@ const DEFAULT_TABLE_PAGE_SIZE = getDefaultPageSize("table");
|
|||
|
||||
export default function Logs() {
|
||||
const { t } = useTranslation();
|
||||
const [activeTab, setActiveTab] = useState("OPERATION");
|
||||
const [activeTab, setActiveTab] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState<SysLog[]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
|
@ -42,7 +43,7 @@ export default function Logs() {
|
|||
sortField: "createdAt",
|
||||
sortOrder: "descend" as any
|
||||
});
|
||||
const { items: logTypeDict } = useDict("sys_log_type");
|
||||
const { items: logTypeDict, loading: logTypeLoading } = useDict("sys_log_type");
|
||||
const { items: logStatusDict } = useDict("sys_log_status");
|
||||
|
||||
const userProfile = useMemo(() => {
|
||||
|
|
@ -60,21 +61,36 @@ export default function Logs() {
|
|||
if (!isPlatformAdmin || !params.tenantId) return t("logsExt.allTenants");
|
||||
return tenants.find((tenant) => tenant.id === params.tenantId)?.tenantName || t("logsExt.tenantId", { id: params.tenantId });
|
||||
}, [isPlatformAdmin, params.tenantId, tenants, t]);
|
||||
const activeLogTypeLabel = useMemo(() => {
|
||||
const dictLabel = logTypeDict.find((item) => item.itemValue === activeTab)?.itemLabel;
|
||||
if (dictLabel) return dictLabel;
|
||||
return activeTab === "OPERATION" ? t("logs.opLog") : t("logs.loginLog");
|
||||
}, [activeTab, logTypeDict, t]);
|
||||
const tabItems = useMemo(() => {
|
||||
if (logTypeDict.length > 0) {
|
||||
return logTypeDict.map((item) => ({
|
||||
key: item.itemValue,
|
||||
label: item.itemLabel,
|
||||
}));
|
||||
}
|
||||
|
||||
const tabItems = logTypeDict.length > 0
|
||||
? logTypeDict.map((item) => ({
|
||||
key: item.itemValue,
|
||||
label: item.itemLabel,
|
||||
}))
|
||||
: [
|
||||
if (logTypeLoading) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{ key: "OPERATION", label: t("logs.opLog") },
|
||||
{ key: "LOGIN", label: t("logs.loginLog") },
|
||||
];
|
||||
}, [logTypeDict, logTypeLoading, t]);
|
||||
|
||||
const activeLogTypeLabel = useMemo(() => {
|
||||
const activeItem = tabItems.find((item) => item.key === activeTab) || tabItems[0];
|
||||
if (activeItem?.label) return activeItem.label;
|
||||
return activeTab === "LOGIN" ? t("logs.loginLog") : t("logs.opLog");
|
||||
}, [activeTab, tabItems, t]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!tabItems.length) return;
|
||||
if (!activeTab || !tabItems.some((item) => item.key === activeTab)) {
|
||||
setActiveTab(tabItems[0].key);
|
||||
}
|
||||
}, [activeTab, tabItems]);
|
||||
|
||||
const cleanAction = (
|
||||
<Popconfirm
|
||||
|
|
@ -85,13 +101,14 @@ export default function Logs() {
|
|||
okButtonProps={{ danger: true, loading: cleaning }}
|
||||
onConfirm={() => void handleClean()}
|
||||
>
|
||||
<Button danger className="logs-clean-action" icon={<DeleteOutlined aria-hidden="true" />} loading={cleaning}>
|
||||
<Button danger className="logs-clean-action" icon={<DeleteOutlined aria-hidden="true" />} loading={cleaning} disabled={!activeTab}>
|
||||
{t("logsExt.cleanCurrent", { type: activeLogTypeLabel })}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
|
||||
const loadData = async (currentParams = params) => {
|
||||
if (!activeTab) return;
|
||||
const requestSeq = requestSeqRef.current + 1;
|
||||
requestSeqRef.current = requestSeq;
|
||||
setLoading(true);
|
||||
|
|
@ -172,6 +189,7 @@ export default function Logs() {
|
|||
};
|
||||
|
||||
const handleClean = async () => {
|
||||
if (!activeTab) return;
|
||||
setCleaning(true);
|
||||
try {
|
||||
await cleanLogs(activeTab, isPlatformAdmin ? params.tenantId : undefined);
|
||||
|
|
@ -207,8 +225,9 @@ export default function Logs() {
|
|||
title: activeTab === "OPERATION" ? t("logsExt.actionLabel") : t("logs.opDetail"),
|
||||
dataIndex: activeTab === "OPERATION" ? "actionName" : "operation",
|
||||
key: activeTab === "OPERATION" ? "actionName" : "operation",
|
||||
ellipsis: true,
|
||||
render: (_: string, record: SysLog) => <Text type="secondary">{record.actionName || record.operation}</Text>
|
||||
width: activeTab === "OPERATION" ? 360 : 300,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (_: string, record: SysLog) => <LongTextPreview value={record.actionName || record.operation} textType="secondary" />
|
||||
},
|
||||
{
|
||||
title: t("logs.ip"),
|
||||
|
|
@ -393,7 +412,7 @@ export default function Logs() {
|
|||
loading={loading}
|
||||
onChange={handleTableChange}
|
||||
totalCount={total}
|
||||
scroll={{ y: "100%" }}
|
||||
scroll={{ x: "max(100%, 1080px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import DataListPanel from "@/components/shared/DataListPanel";
|
|||
import ListTable from "@/components/shared/ListTable/ListTable";
|
||||
import AppPagination from "@/components/shared/AppPagination";
|
||||
import SectionCard from "@/components/shared/SectionCard";
|
||||
import LongTextPreview from "@/components/shared/LongTextPreview";
|
||||
import type { SysParamQuery, SysParamVO } from "@/types";
|
||||
import "./index.less";
|
||||
|
||||
|
|
@ -160,6 +161,7 @@ export default function SysParams() {
|
|||
title: t("sysParams.paramKey"),
|
||||
dataIndex: "paramKey",
|
||||
key: "paramKey",
|
||||
width: 320,
|
||||
render: (text: string, record: SysParamVO) => (
|
||||
<Space direction="vertical" size={0}>
|
||||
<Text className="param-key-text">{text}</Text>
|
||||
|
|
@ -172,6 +174,7 @@ export default function SysParams() {
|
|||
dataIndex: "paramValue",
|
||||
key: "paramValue",
|
||||
width: 360,
|
||||
ellipsis: { showTitle: false },
|
||||
render: (text: string, record: SysParamVO) => {
|
||||
const type = record.paramType;
|
||||
// Boolean: 彩色标签显示 是/否
|
||||
|
|
@ -181,40 +184,10 @@ export default function SysParams() {
|
|||
}
|
||||
// JSON: 等宽字体,以纯字符串显示
|
||||
if (isType(type, "JSON")) {
|
||||
return (
|
||||
<Tooltip title={text}>
|
||||
<Text
|
||||
code
|
||||
style={{
|
||||
display: "block",
|
||||
maxWidth: "100%",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap"
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
);
|
||||
return <LongTextPreview value={text} code />;
|
||||
}
|
||||
// Number / String: 等宽代码文本 + Tooltip
|
||||
return (
|
||||
<Tooltip title={text}>
|
||||
<Text
|
||||
code
|
||||
style={{
|
||||
display: "block",
|
||||
maxWidth: "100%",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap"
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
);
|
||||
// 数字和字符串:等宽代码文本,悬浮查看完整内容。
|
||||
return <LongTextPreview value={text} code />;
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -224,7 +197,7 @@ export default function SysParams() {
|
|||
width: 120,
|
||||
render: (type: string) => <Tag className="param-type-tag">{type || t("sysParamsExt.defaultType")}</Tag>
|
||||
},
|
||||
{ title: t("sysParams.description"), dataIndex: "description", key: "description", ellipsis: true },
|
||||
{ title: t("sysParams.description"), dataIndex: "description", key: "description", width: 360, ellipsis: true },
|
||||
{
|
||||
title: t("common.status"),
|
||||
dataIndex: "status",
|
||||
|
|
@ -298,7 +271,7 @@ export default function SysParams() {
|
|||
columns={columns}
|
||||
dataSource={data}
|
||||
loading={loading}
|
||||
scroll={{ y: "100%" }}
|
||||
scroll={{ x: "max(100%, 1350px)", y: "100%" }}
|
||||
pagination={false}
|
||||
/>
|
||||
</DataListPanel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue