Jelajahi Sumber

!846 perf: 优化 copy 兼容性
Merge pull request !846 from 半栈幼儿员/hotfix/copy

芋道源码 1 bulan lalu
induk
melakukan
d9cbc42811

+ 1 - 1
src/components/MarkdownView/index.vue

@@ -17,7 +17,7 @@ const props = defineProps({
 })
 
 const message = useMessage() // 消息弹窗
-const { copy } = useClipboard() // 初始化 copy 到粘贴板
+const { copy } = useClipboard({ legacy: true }) // 初始化 copy 到粘贴板
 const contentRef = ref()
 
 const md = new MarkdownIt({

+ 8 - 4
src/components/UploadFile/src/useUpload.ts

@@ -1,5 +1,9 @@
 import * as FileApi from '@/api/infra/file'
-import { UploadRawFile, UploadRequestOptions, UploadProgressEvent } from 'element-plus/es/components/upload/src/upload'
+import {
+  UploadRawFile,
+  UploadRequestOptions,
+  UploadProgressEvent
+} from 'element-plus/es/components/upload/src/upload'
 import axios, { AxiosProgressEvent } from 'axios'
 
 /**
@@ -19,7 +23,7 @@ export const useUpload = (directory?: string) => {
     // 文件上传进度监听
     const uploadProgressHandler = (evt: AxiosProgressEvent) => {
       const upEvt: UploadProgressEvent = Object.assign(evt.event)
-      upEvt.percent = evt.progress ? (evt.progress * 100) : 0
+      upEvt.percent = evt.progress ? evt.progress * 100 : 0
       options.onProgress(upEvt) // 触发 el-upload 的 on-progress
     }
 
@@ -33,7 +37,7 @@ export const useUpload = (directory?: string) => {
       return axios
         .put(presignedInfo.uploadUrl, options.file, {
           headers: {
-            'Content-Type': options.file.type
+            'Content-Type': options.file.type || 'application/octet-stream'
           },
           onUploadProgress: uploadProgressHandler
         })
@@ -80,7 +84,7 @@ function createFile(vo: FileApi.FilePresignedUrlRespVO, file: UploadRawFile, fil
     url: vo.url,
     path: vo.path,
     name: fileName,
-    type: file.type,
+    type: file.type || 'application/octet-stream',
     size: file.size
   }
   FileApi.createFile(fileVo)

+ 2 - 1
src/layout/components/Setting/src/Setting.vue

@@ -109,6 +109,7 @@ watch(
 // 拷贝
 const copyConfig = async () => {
   const { copy, copied, isSupported } = useClipboard({
+    legacy: true,
     source: `
       // 面包屑
       breadcrumb: ${appStore.getBreadcrumb},
@@ -296,7 +297,7 @@ const clear = () => {
 $prefix-cls: #{$namespace}-setting;
 
 .#{$prefix-cls} {
+  z-index: 1200; /* 修正没有z-index会被表格层覆盖,值不要超过4000 */
   border-radius: 6px 0 0 6px;
-  z-index: 1200;/*修正没有z-index会被表格层覆盖,值不要超过4000*/
 }
 </style>

+ 9 - 1
src/router/index.ts

@@ -8,7 +8,15 @@ const router = createRouter({
   history: createWebHistory(import.meta.env.VITE_BASE_PATH), // createWebHashHistory URL带#,createWebHistory URL不带#
   strict: true,
   routes: remainingRouter as RouteRecordRaw[],
-  scrollBehavior: () => ({ left: 0, top: 0 })
+  scrollBehavior: () => {
+    // 新开标签时、返回标签时,滚动条回到顶部,否则会保留上次标签的滚动位置。
+    const scrollbarWrap = document.querySelector('.v-layout-content-scrollbar .el-scrollbar__wrap')
+    if (scrollbarWrap) {
+      // scrollbarWrap.scrollTo({ left: 0, top: 0, behavior: 'auto' })
+      scrollbarWrap.scrollTop = 0
+    }
+    return { left: 0, top: 0 }
+  }
 })
 
 export const resetRouter = (): void => {

+ 1 - 1
src/views/ai/chat/index/components/message/MessageList.vue

@@ -126,7 +126,7 @@ import userAvatarDefaultImg from '@/assets/imgs/avatar.gif'
 import roleAvatarDefaultImg from '@/assets/ai/gpt.svg'
 
 const message = useMessage() // 消息弹窗
-const { copy } = useClipboard() // 初始化 copy 到粘贴板
+const { copy } = useClipboard({ legacy: true }) // 初始化 copy 到粘贴板
 const userStore = useUserStore()
 
 // 判断“消息列表”滚动的位置(用于判断是否需要滚动到消息最下方)

+ 1 - 1
src/views/ai/write/index/components/Right.vue

@@ -45,7 +45,7 @@
 import { useClipboard } from '@vueuse/core'
 
 const message = useMessage() // 消息弹窗
-const { copied, copy } = useClipboard() // 粘贴板
+const { copied, copy } = useClipboard({ legacy: true }) // 粘贴板
 
 const props = defineProps({
   content: {

+ 1 - 1
src/views/infra/build/index.vue

@@ -136,7 +136,7 @@ const makeTemplate = () => {
 /** 复制 **/
 const copy = async (text: string) => {
   const textToCopy = JSON.stringify(text, null, 2)
-  const { copy, copied, isSupported } = useClipboard({ source: textToCopy })
+  const { copy, copied, isSupported } = useClipboard({ legacy: true, source: textToCopy })
   if (!isSupported) {
     message.error(t('common.copyError'))
   } else {

+ 1 - 1
src/views/infra/codegen/PreviewCode.vue

@@ -180,7 +180,7 @@ const handleFiles = (datas: CodegenApi.CodegenPreviewVO[]) => {
 
 /** 复制 **/
 const copy = async (text: string) => {
-  const { copy, copied, isSupported } = useClipboard({ source: text })
+  const { copy, copied, isSupported } = useClipboard({ legacy: true, source: text })
   if (!isSupported) {
     message.error(t('common.copyError'))
     return

+ 10 - 23
src/views/infra/file/index.vue

@@ -136,6 +136,7 @@ import { fileSizeFormatter } from '@/utils'
 import { dateFormatter } from '@/utils/formatTime'
 import * as FileApi from '@/api/infra/file'
 import FileForm from './FileForm.vue'
+import { useClipboard } from '@vueuse/core'
 
 defineOptions({ name: 'InfraFile' })
 
@@ -186,29 +187,15 @@ const openForm = () => {
 }
 
 /** 复制到剪贴板方法 */
-const copyToClipboard = (text: string) => {
-  if (navigator.clipboard && window.isSecureContext) {
-    navigator.clipboard
-      .writeText(text)
-      .then(() => {
-        message.success('复制成功')
-      })
-      .catch(() => {
-        message.error('复制失败')
-      })
-  } else {
-    // 兼容不支持 clipboard 的情况
-    try {
-      const textarea = document.createElement('textarea')
-      textarea.value = text
-      document.body.appendChild(textarea)
-      textarea.select()
-      document.execCommand('copy')
-      document.body.removeChild(textarea)
-      message.success('复制成功')
-    } catch (error) {
-      message.error('复制失败')
-    }
+const copyToClipboard = async (text: string) => {
+  const { copy, copied, isSupported } = useClipboard({ legacy: true, source: text })
+  if (!isSupported) {
+    message.error(t('common.copyError'))
+    return
+  }
+  await copy()
+  if (unref(copied)) {
+    message.success(t('common.copySuccess'))
   }
 }
 

+ 10 - 5
src/views/iot/device/device/detail/DeviceDetailsHeader.vue

@@ -39,8 +39,10 @@
 import DeviceForm from '@/views/iot/device/device/DeviceForm.vue'
 import { ProductVO } from '@/api/iot/product/product'
 import { DeviceVO } from '@/api/iot/device/device'
+import { useClipboard } from '@vueuse/core'
 
 const message = useMessage()
+const { t } = useI18n() // 国际化
 const router = useRouter()
 
 const { product, device } = defineProps<{ product: ProductVO; device: DeviceVO }>()
@@ -54,11 +56,14 @@ const openForm = (type: string, id?: number) => {
 
 /** 复制到剪贴板方法 */
 const copyToClipboard = async (text: string) => {
-  try {
-    await navigator.clipboard.writeText(text)
-    message.success('复制成功')
-  } catch (error) {
-    message.error('复制失败')
+  const { copy, copied, isSupported } = useClipboard({ legacy: true, source: text })
+  if (!isSupported) {
+    message.error(t('common.copyError'))
+    return
+  }
+  await copy()
+  if (unref(copied)) {
+    message.success(t('common.copySuccess'))
   }
 }
 

+ 10 - 5
src/views/iot/device/device/detail/DeviceDetailsInfo.vue

@@ -140,8 +140,10 @@ import { DeviceVO } from '@/api/iot/device/device'
 import { DeviceApi, IotDeviceAuthInfoVO } from '@/api/iot/device/device'
 import Map from '@/components/Map/index.vue'
 import { ref, computed } from 'vue'
+import { useClipboard } from '@vueuse/core'
 
 const message = useMessage() // 消息提示
+const { t } = useI18n() // 国际化
 
 const { product, device } = defineProps<{ product: ProductVO; device: DeviceVO }>() // 定义 Props
 const emit = defineEmits(['refresh']) // 定义 Emits
@@ -165,11 +167,14 @@ const getLocationString = () => {
 
 /** 复制到剪贴板方法 */
 const copyToClipboard = async (text: string) => {
-  try {
-    await navigator.clipboard.writeText(text)
-    message.success('复制成功')
-  } catch (error) {
-    message.error('复制失败')
+  const { copy, copied, isSupported } = useClipboard({ legacy: true, source: text })
+  if (!isSupported) {
+    message.error(t('common.copyError'))
+    return
+  }
+  await copy()
+  if (unref(copied)) {
+    message.success(t('common.copySuccess'))
   }
 }
 

+ 10 - 5
src/views/iot/product/product/detail/ProductDetailsHeader.vue

@@ -54,18 +54,23 @@
 <script setup lang="ts">
 import ProductForm from '@/views/iot/product/product/ProductForm.vue'
 import { ProductApi, ProductVO } from '@/api/iot/product/product'
+import { useClipboard } from '@vueuse/core'
 
 const message = useMessage()
+const { t } = useI18n() // 国际化
 
 const { product } = defineProps<{ product: ProductVO }>() // 定义 Props
 
 /** 复制到剪贴板方法 */
 const copyToClipboard = async (text: string) => {
-  try {
-    await navigator.clipboard.writeText(text)
-    message.success('复制成功')
-  } catch (error) {
-    message.error('复制失败')
+  const { copy, copied, isSupported } = useClipboard({ legacy: true, source: text })
+  if (!isSupported) {
+    message.error(t('common.copyError'))
+    return
+  }
+  await copy()
+  if (unref(copied)) {
+    message.success(t('common.copySuccess'))
   }
 }