chore(ui): about

This commit is contained in:
Fu Diwei 2025-09-10 21:05:16 +08:00
parent a63cd91ac6
commit 4c933c05ab
9 changed files with 144 additions and 21 deletions

View File

@ -11,14 +11,10 @@ export interface AppDocumentLinkButtonProps {
}
const AppDocumentLinkButton = ({ className, style, showIcon = true }: AppDocumentLinkButtonProps) => {
const { i18n, t } = useTranslation();
const { t } = useTranslation();
const handleDocumentClick = () => {
if (i18n.language.startsWith("en")) {
window.open(APP_DOCUMENT_URL + "/en/", "_blank");
} else {
window.open(APP_DOCUMENT_URL, "_blank");
}
window.open(APP_DOCUMENT_URL, "_blank");
};
return (

View File

@ -1,8 +1,16 @@
export const APP_REPO_URL = "https://github.com/certimate-go/certimate";
export const APP_DOWNLOAD_URL = APP_REPO_URL + "/releases";
export const APP_DOCUMENT_URL = "https://docs.certimate.me";
import i18next from "i18next";
// fallback policy: .env > git tag > "v0.0.0-dev"
export const APP_VERSION: string = import.meta.env.VITE_APP_VERSION || __APP_VERSION__ || "v0.0.0-dev";
export const APP_REPO_URL = "https://github.com/certimate-go/certimate";
export const APP_DOWNLOAD_URL = APP_REPO_URL + "/releases";
export let APP_DOCUMENT_URL = "https://docs.certimate.me";
i18next.on("languageChanged", (language) => {
if (language.startsWith("zh")) {
APP_DOCUMENT_URL = "https://docs.certimate.me";
} else {
APP_DOCUMENT_URL = "https://docs.certimate.me/en/";
}
});

View File

@ -57,5 +57,17 @@
"settings.diagnostics.workflow_dispatcher.title": "Workflow dispatcher",
"settings.diagnostics.workflow_dispatcher.statistics.concurrency": "Concurrency",
"settings.diagnostics.workflow_dispatcher.statistics.pending": "Pending",
"settings.diagnostics.workflow_dispatcher.statistics.processing": "Processing"
"settings.diagnostics.workflow_dispatcher.statistics.processing": "Processing",
"settings.about.tab": "About",
"settings.about.version.new": "New version available",
"settings.about.socials.document": "Documentation",
"settings.about.socials.github": "GitHub",
"settings.about.socials.telegram": "Telegram",
"settings.about.socials.donate": "Donate",
"settings.about.feedback.title": "Help us improve Certimate",
"settings.about.feedback.subtitle": "Tell us how to make Certimate work better for you.",
"settings.about.feedback.button": "Give feedback",
"settings.about.contributors.title": "Contributors",
"settings.about.contributors.tips": "Thanks to all the people who have contributed to this project."
}

View File

@ -57,5 +57,17 @@
"settings.diagnostics.workflow_dispatcher.title": "工作流调度器",
"settings.diagnostics.workflow_dispatcher.statistics.concurrency": "最大并发",
"settings.diagnostics.workflow_dispatcher.statistics.pending": "等待运行",
"settings.diagnostics.workflow_dispatcher.statistics.processing": "运行中"
"settings.diagnostics.workflow_dispatcher.statistics.processing": "运行中",
"settings.about.tab": "关于",
"settings.about.version.new": "有新版本可更新",
"settings.about.socials.document": "文档",
"settings.about.socials.github": "GitHub",
"settings.about.socials.telegram": "Telegram",
"settings.about.socials.donate": "捐赠",
"settings.about.feedback.title": "帮助我们改进 Certimate",
"settings.about.feedback.subtitle": "告诉我们如何让 Certimate 为你更好地服务。",
"settings.about.feedback.button": "意见反馈",
"settings.about.contributors.title": "贡献者",
"settings.about.contributors.tips": "感谢所有贡献者对本项目做出的贡献。"
}

View File

@ -28,7 +28,7 @@ import { isBrowserHappy } from "@/utils/browser";
const ConsoleLayout = () => {
const navigate = useNavigate();
const { i18n, t } = useTranslation();
const { t } = useTranslation();
const { token: themeToken } = theme.useToken();
@ -40,11 +40,7 @@ const ConsoleLayout = () => {
};
const handleDocumentClick = () => {
if (i18n.language.startsWith("zh")) {
window.open(APP_DOCUMENT_URL, "_blank");
} else {
window.open(APP_DOCUMENT_URL + "/en/", "_blank");
}
window.open(APP_DOCUMENT_URL, "_blank");
};
const handleGitHubClick = () => {

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Outlet, useLocation, useNavigate } from "react-router-dom";
import { IconBracketsAngle, IconDatabaseCog, IconPalette, IconPlugConnected, IconUserShield } from "@tabler/icons-react";
import { IconBracketsAngle, IconDatabaseCog, IconInfoCircle, IconPalette, IconPlugConnected, IconUserShield } from "@tabler/icons-react";
import { Menu } from "antd";
const Settings = () => {
@ -16,6 +16,7 @@ const Settings = () => {
["ssl-provider", "settings.sslprovider.tab", <IconPlugConnected size="1em" />],
["persistence", "settings.persistence.tab", <IconDatabaseCog size="1em" />],
["diagnostics", "settings.diagnostics.tab", <IconBracketsAngle size="1em" />],
["about", "settings.about.tab", <IconInfoCircle size="1em" />],
] satisfies [string, string, React.ReactElement][];
const [menuKey, setMenuKey] = useState<string>(() => location.pathname.split("/")[2]);
useEffect(() => {

View File

@ -0,0 +1,88 @@
import { useTranslation } from "react-i18next";
import { IconBook, IconBrandGithub, IconBrandTelegram, IconCoin, IconMessageChatbot } from "@tabler/icons-react";
import { Badge, Button, Divider, List, Tooltip, Typography } from "antd";
import { APP_DOCUMENT_URL, APP_DOWNLOAD_URL, APP_REPO_URL, APP_VERSION } from "@/domain/app";
import { useVersionChecker } from "@/hooks";
const SettingsAbout = () => {
const { t } = useTranslation();
const { hasUpdate } = useVersionChecker();
const handleDownloadClick = () => {
window.open(APP_DOWNLOAD_URL, "_blank");
};
const handleDocumentClick = () => {
window.open(APP_DOCUMENT_URL, "_blank");
};
const handleGithubClick = () => {
window.open(APP_REPO_URL, "_blank");
};
const handleTelegramClick = () => {
window.open("https://t.me/+ZXphsppxUg41YmVl", "_blank");
};
const handleDonateClick = () => {
window.open("https://profile.ikit.fun/sponsors/", "_blank");
};
const handleFeedbackClick = () => {
window.open(APP_REPO_URL + "/issues", "_blank");
};
return (
<>
<h2>Certimate</h2>
<div className="mb-4">
<div className="flex items-center gap-2">
<Typography.Text type="secondary">Version: {APP_VERSION}</Typography.Text>
<Badge className="cursor-pointer" count={hasUpdate ? t("settings.about.version.new") : void 0} onClick={handleDownloadClick} />
</div>
</div>
<div className="mb-2 flex flex-wrap items-center gap-2">
<Tooltip title={t("settings.about.socials.document")}>
<Button type="text" icon={<IconBook size="1.5em" onClick={handleDocumentClick} />} />
</Tooltip>
<Tooltip title={t("settings.about.socials.github")}>
<Button type="text" icon={<IconBrandGithub size="1.5em" onClick={handleGithubClick} />} />
</Tooltip>
<Tooltip title={t("settings.about.socials.telegram")}>
<Button type="text" icon={<IconBrandTelegram size="1.5em" onClick={handleTelegramClick} />} />
</Tooltip>
<Tooltip title={t("settings.about.socials.donate")}>
<Button type="text" icon={<IconCoin size="1.5em" onClick={handleDonateClick} />} />
</Tooltip>
</div>
<Divider />
<h2>{t("settings.about.contributors.title")}</h2>
<div className="mb-4">
<Typography.Text type="secondary">{t("settings.about.contributors.tips")}</Typography.Text>
</div>
<div className="mb-2">
<img className="max-w-full" src="https://contrib.rocks/image?repo=certimate-go/certimate" alt="Contributors" />
</div>
<Divider />
<div className="md:max-w-160">
<List bordered>
<List.Item extra={<Button onClick={handleFeedbackClick}>{t("settings.about.feedback.button")}</Button>}>
<List.Item.Meta
avatar={<IconMessageChatbot size="1.5em" />}
title={t("settings.about.feedback.title")}
description={t("settings.about.feedback.subtitle")}
/>
</List.Item>
</List>
</div>
</>
);
};
export default SettingsAbout;

View File

@ -306,7 +306,7 @@ const SettingsDiagnosticsWorkflowDispatcher = ({ className, style }: { className
type Statistics = Awaited<ReturnType<typeof getWorkflowStats>>["data"];
const [statistics, setStatistics] = useState<Statistics>();
const { loading } = useRequest(
const { loading, cancel } = useRequest(
() => {
return getWorkflowStats();
},
@ -318,6 +318,11 @@ const SettingsDiagnosticsWorkflowDispatcher = ({ className, style }: { className
onSuccess: (res) => {
setStatistics(res.data);
},
onError: () => {
if (!statistics) {
cancel();
}
},
}
);

View File

@ -9,6 +9,7 @@ import Dashboard from "@/pages/dashboard/Dashboard";
import ErrorLayout from "@/pages/ErrorLayout";
import Login from "@/pages/login/Login";
import Settings from "@/pages/settings/Settings";
import SettingsAbout from "@/pages/settings/SettingsAbout";
import SettingsAccount from "@/pages/settings/SettingsAccount";
import SettingsAppearance from "@/pages/settings/SettingsAppearance";
import SettingsDiagnostics from "@/pages/settings/SettingsDiagnostics";
@ -87,6 +88,10 @@ export const router = createHashRouter([
path: "/settings/diagnostics",
element: <SettingsDiagnostics />,
},
{
path: "/settings/about",
element: <SettingsAbout />,
},
],
},
],