diff --git a/frontend/src/components/CopyButton.vue b/frontend/src/components/CopyButton.vue
index fcf967b2..91a692d5 100644
--- a/frontend/src/components/CopyButton.vue
+++ b/frontend/src/components/CopyButton.vue
@@ -1,39 +1,21 @@
{{ t("TXT_CODE_13ae6a93") }}
-
+
diff --git a/frontend/src/components/MyselfInfoDialog.vue b/frontend/src/components/MyselfInfoDialog.vue
index beccbc6d..295c6238 100644
--- a/frontend/src/components/MyselfInfoDialog.vue
+++ b/frontend/src/components/MyselfInfoDialog.vue
@@ -10,6 +10,7 @@ import type { FormInstance } from "ant-design-vue";
import CopyButton from "@/components/CopyButton.vue";
import { bind2FA } from "../services/apis/user";
import { PERMISSION_MAP } from "@/config/const";
+import { toCopy } from "@/tools/copy";
const { state, updateUserInfo } = useAppStateStore();
const { state: tools } = useAppToolsStore();
@@ -176,7 +177,6 @@ const disable2FACode = async () => {
-
{{ t("TXT_CODE_b2dbf778") }}
diff --git a/frontend/src/tools/copy.ts b/frontend/src/tools/copy.ts
new file mode 100644
index 00000000..8807d624
--- /dev/null
+++ b/frontend/src/tools/copy.ts
@@ -0,0 +1,29 @@
+import { t } from "@/lang/i18n";
+import { useClipboard } from "@vueuse/core";
+import { message, Modal } from "ant-design-vue";
+import { h } from "vue";
+
+const { copy, copied, isSupported } = useClipboard();
+
+export const toCopy = async (sth: string | number) => {
+ try {
+ if (!isSupported.value) {
+ const input = document.createElement("input");
+ input.setAttribute("value", String(sth));
+ document.body.appendChild(input);
+ input.select();
+ document.execCommand("copy");
+ document.body.removeChild(input);
+ return message.success(t("TXT_CODE_b858d78a"));
+ } else {
+ await copy(String(sth));
+ if (copied.value) return message.success(t("TXT_CODE_b858d78a"));
+ }
+ } catch (err: any) {
+ console.error(err);
+ Modal.warning({
+ title: t("TXT_CODE_ca07c84c"),
+ content: [h("span", t("TXT_CODE_2452016e")), h("br"), h("span", sth)]
+ });
+ }
+};