diff --git a/src/components/Editor/src/Editor.vue b/src/components/Editor/src/Editor.vue index 36fe1650..30146be3 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) { diff --git a/src/components/MarkdownView/index.vue b/src/components/MarkdownView/index.vue index 74764d59..86fc9391 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/components/UploadFile/src/useUpload.ts b/src/components/UploadFile/src/useUpload.ts index 8f316eb5..dddd1596 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) diff --git a/src/layout/components/Setting/src/Setting.vue b/src/layout/components/Setting/src/Setting.vue index 2973674b..92ecf414 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/router/index.ts b/src/router/index.ts index e80dae08..4e861c6c 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 => { diff --git a/src/views/ai/chat/index/components/message/MessageList.vue b/src/views/ai/chat/index/components/message/MessageList.vue index 77b41c79..da5c338a 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 d0aada5d..1eb66a07 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 260b8b7a..191fc90f 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 b6a307d2..819fca6c 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 a0c9e258..e431218d 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 6fc876bc..c6d031fd 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 930adb67..e3beda75 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 3eb999fa..311900c2 100644 --- a/src/views/iot/product/product/detail/ProductDetailsHeader.vue +++ b/src/views/iot/product/product/detail/ProductDetailsHeader.vue @@ -54,18 +54,23 @@