From 2a9d07f514f45227c7ba1241322880ab3c89c8f0 Mon Sep 17 00:00:00 2001 From: preschooler Date: Sun, 28 Dec 2025 20:40:06 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=AF=8C=E6=96=87=E6=9C=AC=E7=BC=96=E8=BE=91=E5=99=A8=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E4=B8=8A=E4=BC=A0=E5=90=8C=E4=B8=80=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E3=80=81=E6=B7=BB=E5=8A=A0=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Editor/src/Editor.vue | 35 ++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/components/Editor/src/Editor.vue b/src/components/Editor/src/Editor.vue index 36fe1650f..30146be37 100644 --- a/src/components/Editor/src/Editor.vue +++ b/src/components/Editor/src/Editor.vue @@ -28,7 +28,8 @@ const props = defineProps({ default: () => undefined }, readonly: propTypes.bool.def(false), - modelValue: propTypes.string.def('') + modelValue: propTypes.string.def(''), + directory: propTypes.string.def('editor-default') }) const emit = defineEmits(['change', 'update:modelValue']) @@ -115,9 +116,9 @@ const editorConfig = computed((): IEditorConfig => { ['uploadImage']: { server: getUploadUrl(), // 单个文件的最大体积限制,默认为 2M - maxFileSize: 5 * 1024 * 1024, + maxFileSize: 10 * 1024 * 1024, // 最多可上传几个文件,默认为 100 - maxNumberOfFiles: 10, + maxNumberOfFiles: 100, // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 [] allowedFileTypes: ['image/*'], @@ -133,6 +134,19 @@ const editorConfig = computed((): IEditorConfig => { // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image fieldName: 'file', + // 附加参数 + meta: { + directory: `${props.directory}-image` + }, + metaWithUrl: false, + + // uppy 配置项 + uppyConfig: { + onBeforeFileAdded: (newFile: any) => { + newFile.id = `${newFile.id}-${Date.now()}` + return newFile + } + }, // 上传之前触发 onBeforeUpload(file: File) { @@ -163,7 +177,7 @@ const editorConfig = computed((): IEditorConfig => { ['uploadVideo']: { server: getUploadUrl(), // 单个文件的最大体积限制,默认为 10M - maxFileSize: 10 * 1024 * 1024, + maxFileSize: 1024 * 1024 * 1024, // 最多可上传几个文件,默认为 100 maxNumberOfFiles: 10, // 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 [] @@ -181,6 +195,19 @@ const editorConfig = computed((): IEditorConfig => { // form-data fieldName,后端接口参数名称,默认值wangeditor-uploaded-image fieldName: 'file', + // 附加参数 + meta: { + directory: `${props.directory}-video` + }, + metaWithUrl: false, + + // uppy 配置项 + uppyConfig: { + onBeforeFileAdded: (newFile: any) => { + newFile.id = `${newFile.id}-${Date.now()}` + return newFile + } + }, // 上传之前触发 onBeforeUpload(file: File) { From 9af4cad55246c416f4b40adb0e5a5e120e97ba50 Mon Sep 17 00:00:00 2001 From: preschooler Date: Sun, 28 Dec 2025 21:15:44 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E7=A1=AE=E4=BF=9D?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E6=97=B6=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=20Content-Type=EF=BC=8C=E5=90=A6=E5=88=99=E4=BC=9A=E5=BC=82?= =?UTF-8?q?=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/UploadFile/src/useUpload.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/UploadFile/src/useUpload.ts b/src/components/UploadFile/src/useUpload.ts index 8f316eb59..dddd15961 100644 --- a/src/components/UploadFile/src/useUpload.ts +++ b/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) From ee7c73b4751f341a3c91388f781a227e83fe0d82 Mon Sep 17 00:00:00 2001 From: preschooler Date: Sun, 28 Dec 2025 21:18:03 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E6=96=B0=E5=BC=80?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E6=97=B6=E3=80=81=E8=BF=94=E5=9B=9E=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E6=97=B6=EF=BC=8C=E6=BB=9A=E5=8A=A8=E6=9D=A1=E5=9B=9E?= =?UTF-8?q?=E5=88=B0=E9=A1=B6=E9=83=A8=EF=BC=8C=E5=90=A6=E5=88=99=E4=BC=9A?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E4=B8=8A=E6=AC=A1=E6=A0=87=E7=AD=BE=E7=9A=84?= =?UTF-8?q?=E6=BB=9A=E5=8A=A8=E4=BD=8D=E7=BD=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/index.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/router/index.ts b/src/router/index.ts index e80dae08e..4e861c6c5 100644 --- a/src/router/index.ts +++ b/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 => { From 394c94b67c07fb3065ccef22378e2b5c1042118d Mon Sep 17 00:00:00 2001 From: preschooler Date: Sun, 28 Dec 2025 22:14:42 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=8E=88=20perf:=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20copy=20=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/MarkdownView/index.vue | 2 +- src/layout/components/Setting/src/Setting.vue | 3 +- .../index/components/message/MessageList.vue | 2 +- src/views/ai/write/index/components/Right.vue | 2 +- src/views/infra/build/index.vue | 2 +- src/views/infra/codegen/PreviewCode.vue | 2 +- src/views/infra/file/index.vue | 33 ++++++------------- .../device/detail/DeviceDetailsHeader.vue | 15 ++++++--- .../device/detail/DeviceDetailsInfo.vue | 15 ++++++--- .../product/detail/ProductDetailsHeader.vue | 15 ++++++--- 10 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/components/MarkdownView/index.vue b/src/components/MarkdownView/index.vue index 74764d592..86fc93917 100644 --- a/src/components/MarkdownView/index.vue +++ b/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({ diff --git a/src/layout/components/Setting/src/Setting.vue b/src/layout/components/Setting/src/Setting.vue index 2973674ba..92ecf4149 100644 --- a/src/layout/components/Setting/src/Setting.vue +++ b/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*/ } diff --git a/src/views/ai/chat/index/components/message/MessageList.vue b/src/views/ai/chat/index/components/message/MessageList.vue index 77b41c796..da5c338a6 100644 --- a/src/views/ai/chat/index/components/message/MessageList.vue +++ b/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() // 判断“消息列表”滚动的位置(用于判断是否需要滚动到消息最下方) diff --git a/src/views/ai/write/index/components/Right.vue b/src/views/ai/write/index/components/Right.vue index d0aada5df..1eb66a077 100644 --- a/src/views/ai/write/index/components/Right.vue +++ b/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: { diff --git a/src/views/infra/build/index.vue b/src/views/infra/build/index.vue index 260b8b7a0..191fc90fe 100644 --- a/src/views/infra/build/index.vue +++ b/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 { diff --git a/src/views/infra/codegen/PreviewCode.vue b/src/views/infra/codegen/PreviewCode.vue index b6a307d23..819fca6c0 100644 --- a/src/views/infra/codegen/PreviewCode.vue +++ b/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 diff --git a/src/views/infra/file/index.vue b/src/views/infra/file/index.vue index a0c9e258b..e431218da 100644 --- a/src/views/infra/file/index.vue +++ b/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')) } } diff --git a/src/views/iot/device/device/detail/DeviceDetailsHeader.vue b/src/views/iot/device/device/detail/DeviceDetailsHeader.vue index 6fc876bc8..c6d031fdb 100644 --- a/src/views/iot/device/device/detail/DeviceDetailsHeader.vue +++ b/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')) } } diff --git a/src/views/iot/device/device/detail/DeviceDetailsInfo.vue b/src/views/iot/device/device/detail/DeviceDetailsInfo.vue index 930adb678..e3beda752 100644 --- a/src/views/iot/device/device/detail/DeviceDetailsInfo.vue +++ b/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')) } } diff --git a/src/views/iot/product/product/detail/ProductDetailsHeader.vue b/src/views/iot/product/product/detail/ProductDetailsHeader.vue index 3eb999fa4..311900c2a 100644 --- a/src/views/iot/product/product/detail/ProductDetailsHeader.vue +++ b/src/views/iot/product/product/detail/ProductDetailsHeader.vue @@ -54,18 +54,23 @@