Bläddra i källkod

Refactor:移除useCopyToClipboard hook, 使用navigator.clipboard进行替代。close #2723 (#3105)

* feat: 重写复制文本功能

* refactor: 替换复制文本示例代码

* chore: delete useCopyToClipboard hook
invalid w 1 år sedan
förälder
incheckning
f3f2f548e6

+ 4 - 20
src/components/Icon/src/IconPicker.vue

@@ -65,7 +65,7 @@
   </a-input>
 </template>
 <script lang="ts" setup>
-  import { ref, watchEffect, watch, unref } from 'vue';
+  import { ref, watchEffect, watch } from 'vue';
   import { useDesign } from '/@/hooks/web/useDesign';
   import { ScrollContainer } from '/@/components/Container';
   import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
@@ -77,10 +77,8 @@
   import { usePagination } from '/@/hooks/web/usePagination';
   import { useDebounceFn } from '@vueuse/core';
   import { useI18n } from '/@/hooks/web/useI18n';
-  import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
-  import { useMessage } from '/@/hooks/web/useMessage';
   import svgIcons from 'virtual:svg-icons-names';
-
+  import { copyText } from '/@/utils/copyTextToClipboard';
   // 没有使用别名引入,是因为WebStorm当前版本还不能正确识别,会报unused警告
   const AInput = Input;
   const APopover = Popover;
@@ -107,7 +105,7 @@
     value: propTypes.string,
     width: propTypes.string.def('100%'),
     pageSize: propTypes.number.def(140),
-    copy: propTypes.bool.def(false),
+    copy: propTypes.bool.def(true),
     mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
   });
 
@@ -125,17 +123,6 @@
 
   const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
 
-  let clipboardRef;
-  let isSuccessRef;
-
-  if (props.copy) {
-    const clipboard = useCopyToClipboard(props.value);
-    clipboardRef = clipboard?.clipboardRef;
-    isSuccessRef = clipboard?.isSuccessRef;
-  }
-
-  const { createMessage } = useMessage();
-
   const { getPaginationList, getTotal, setCurrentPage } = usePagination(
     currentList,
     props.pageSize,
@@ -160,10 +147,7 @@
   function handleClick(icon: string) {
     currentSelect.value = icon;
     if (props.copy) {
-      clipboardRef.value = icon;
-      if (unref(isSuccessRef)) {
-        createMessage.success(t('component.icon.copy'));
-      }
+      copyText(icon, t('component.icon.copy'));
     }
   }
 

+ 0 - 70
src/hooks/web/useCopyToClipboard.ts

@@ -1,70 +0,0 @@
-import { ref, watch } from 'vue';
-
-import { isDef } from '/@/utils/is';
-
-interface Options {
-  target?: HTMLElement;
-}
-export function useCopyToClipboard(initial?: string) {
-  const clipboardRef = ref(initial || '');
-  const isSuccessRef = ref(false);
-  const copiedRef = ref(false);
-
-  watch(
-    clipboardRef,
-    (str?: string) => {
-      if (isDef(str)) {
-        copiedRef.value = true;
-        isSuccessRef.value = copyTextToClipboard(str);
-      }
-    },
-    { immediate: !!initial, flush: 'sync' },
-  );
-
-  return { clipboardRef, isSuccessRef, copiedRef };
-}
-
-export function copyTextToClipboard(input: string, { target = document.body }: Options = {}) {
-  const element = document.createElement('textarea');
-  const previouslyFocusedElement = document.activeElement;
-
-  element.value = input;
-
-  element.setAttribute('readonly', '');
-
-  (element.style as any).contain = 'strict';
-  element.style.position = 'absolute';
-  element.style.left = '-9999px';
-  element.style.fontSize = '12pt';
-
-  const selection = document.getSelection();
-  let originalRange;
-  if (selection && selection.rangeCount > 0) {
-    originalRange = selection.getRangeAt(0);
-  }
-
-  target.append(element);
-  element.select();
-
-  element.selectionStart = 0;
-  element.selectionEnd = input.length;
-
-  let isSuccess = false;
-  try {
-    isSuccess = document.execCommand('copy');
-  } catch (e: any) {
-    throw new Error(e);
-  }
-
-  element.remove();
-
-  if (originalRange && selection) {
-    selection.removeAllRanges();
-    selection.addRange(originalRange);
-  }
-
-  if (previouslyFocusedElement) {
-    (previouslyFocusedElement as HTMLElement).focus();
-  }
-  return isSuccess;
-}

+ 7 - 10
src/layouts/default/setting/components/SettingFooter.vue

@@ -29,8 +29,7 @@
   import { useDesign } from '/@/hooks/web/useDesign';
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useMessage } from '/@/hooks/web/useMessage';
-  import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
-
+  import { copyText } from '/@/utils/copyTextToClipboard';
   import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
   import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
   import defaultSetting from '/@/settings/projectSetting';
@@ -49,14 +48,12 @@
       const appStore = useAppStore();
 
       function handleCopy() {
-        const { isSuccessRef } = useCopyToClipboard(
-          JSON.stringify(unref(appStore.getProjectConfig), null, 2),
-        );
-        unref(isSuccessRef) &&
-          createSuccessModal({
-            title: t('layout.setting.operatingTitle'),
-            content: t('layout.setting.operatingContent'),
-          });
+        copyText(JSON.stringify(unref(appStore.getProjectConfig), null, 2), null);
+
+        createSuccessModal({
+          title: t('layout.setting.operatingTitle'),
+          content: t('layout.setting.operatingContent'),
+        });
       }
       function handleResetSetting() {
         try {

+ 12 - 0
src/utils/copyTextToClipboard.ts

@@ -0,0 +1,12 @@
+import { message } from 'ant-design-vue';
+
+export function copyText(text: string, prompt: string | null = '已成功复制到剪切板!') {
+  navigator.clipboard.writeText(text).then(
+    function () {
+      prompt && message.success(prompt);
+    },
+    function (error: Error) {
+      message.error('复制失败!' + error.message);
+    },
+  );
+}

+ 2 - 6
src/views/demo/feat/copy/index.vue

@@ -11,9 +11,9 @@
 <script lang="ts">
   import { defineComponent, unref, ref } from 'vue';
   import { CollapseContainer } from '/@/components/Container/index';
-  import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { PageWrapper } from '/@/components/Page';
+  import { copyText } from '/@/utils/copyTextToClipboard';
 
   export default defineComponent({
     name: 'Copy',
@@ -21,7 +21,6 @@
     setup() {
       const valueRef = ref('');
       const { createMessage } = useMessage();
-      const { clipboardRef, copiedRef } = useCopyToClipboard();
 
       function handleCopy() {
         const value = unref(valueRef);
@@ -29,10 +28,7 @@
           createMessage.warning('请输入要拷贝的内容!');
           return;
         }
-        clipboardRef.value = value;
-        if (unref(copiedRef)) {
-          createMessage.warning('copy success!');
-        }
+        copyText(value);
       }
       return { handleCopy, value: valueRef };
     },

+ 4 - 7
src/views/form-design/components/VFormDesign/components/PreviewCode.vue

@@ -19,10 +19,10 @@
 </template>
 
 <script lang="ts">
-  import { defineComponent, reactive, toRefs, unref } from 'vue';
+  import { defineComponent, reactive, toRefs } from 'vue';
   import { CodeEditor, MODE } from '/@/components/CodeEditor';
 
-  import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
+  import { copyText } from '/@/utils/copyTextToClipboard';
   import { useMessage } from '/@/hooks/web/useMessage';
 
   export default defineComponent({
@@ -58,7 +58,7 @@
       const handleExportJson = () => {
         exportData(props.editorJson);
       };
-      const { clipboardRef, copiedRef } = useCopyToClipboard();
+
       const { createMessage } = useMessage();
 
       const handleCopyJson = () => {
@@ -68,10 +68,7 @@
           createMessage.warning('代码为空!');
           return;
         }
-        clipboardRef.value = value;
-        if (unref(copiedRef)) {
-          createMessage.warning('复制成功!');
-        }
+        copyText(value);
       };
 
       return {