From 688f0dff328f1a673bad11fa340a8e00b626dfdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E6=98=B1=E8=BE=BE?= Date: Fri, 5 Dec 2025 10:10:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(cropper):=20=E6=B7=BB=E5=8A=A0=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E8=A3=81=E5=89=AA=E7=BB=84=E4=BB=B6=E5=8F=8A=E4=BE=9D?= =?UTF-8?q?=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 Cropper 组件,支持图片裁剪、缩放、旋转功能 - 集成 cropperjs 库及其相关元素组件 - 在专业模式页面中引入并使用裁剪组件 - 更新 package.json 和 lock 文件以包含新依赖 - 优化登录过期弹窗按钮文本显示 --- package-lock.json | 118 +++++++++++ package.json | 1 + src/api/modules/xajax.js | 4 +- src/components/Cropper/Cropper.vue | 187 ++++++++++++++++++ .../components/professionalmode.vue | 15 ++ 5 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 src/components/Cropper/Cropper.vue diff --git a/package-lock.json b/package-lock.json index 187869bb..d3b3e843 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1246,6 +1246,115 @@ "to-fast-properties": "^2.0.0" } }, + "@cropper/element": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element/-/element-2.1.0.tgz", + "integrity": "sha512-2zELddqHQNmlvkPoiYzE5nxEjPE+C8nXoTPuvV3FvLp3YjBinc7qb73Icg9UXP0o9qC4+h9q96JgGo0AyMO/Ng==", + "requires": { + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-canvas": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-canvas/-/element-canvas-2.1.0.tgz", + "integrity": "sha512-el+rfJpZxsD2q5XxDBA4fRczcrOqB65Lb7roqXOq8LKufwf4bPWA9C6DjNJJahh/TP94dsLIEy3tSkgRMDv3Aw==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-crosshair": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-crosshair/-/element-crosshair-2.1.0.tgz", + "integrity": "sha512-0V589dAx8uZAfvJwdINLn76gfPQEafPH94ukjJ76uX0FCUovLaAVX+VRD/MDSYn0Mza/xejzmL9Dhd1DfemvmA==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-grid": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-grid/-/element-grid-2.1.0.tgz", + "integrity": "sha512-dEnk0rO+vp553LMvsPYgfrqVFcYXeVFrgFeavBYYEhAXtO40p7kN4rmLYLMMjaN+T/Mx2BATv6kUQpALKy2HLw==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-handle": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-handle/-/element-handle-2.1.0.tgz", + "integrity": "sha512-8BklWA4C/2GGAULupIWleSnGutECvYt3vx9flodqDfZpDEozws4LgLqmmzVuQmVkRVUdLnXdtx28kjgWLtzkHg==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-image": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-image/-/element-image-2.1.0.tgz", + "integrity": "sha512-mXOV8ixJvG0XtTxLebYAKDjEkFbFOQnsF02hXPZk1yQSV0J+LLhN7a2NePrtKnoTsEV19fhhX3UorMoyGGxvzg==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/element-canvas": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-selection": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-selection/-/element-selection-2.1.0.tgz", + "integrity": "sha512-mtFtBl6HIa/s9TWohXw+Z5eJoeYTqylrIcHvS7oVv0uM7IyeRwBW65Q7z+KtLfq/LW+2Sw/XDyvR+VN/DawBPw==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/element-canvas": "^2.1.0", + "@cropper/element-image": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-shade": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-shade/-/element-shade-2.1.0.tgz", + "integrity": "sha512-zMdyqbb0lc0Vd1oj2Z1miIZvhyZG41OXMHvrNt0hNwblh0dVdrvtw48lnFDgRv+672vt2CNx7Q04GuvCQfPlgg==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/element-canvas": "^2.1.0", + "@cropper/element-selection": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/element-viewer": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/element-viewer/-/element-viewer-2.1.0.tgz", + "integrity": "sha512-XnxlQuqHitd1FOFZ6E0yXAF5NYd/LyIvONLLHI9p1rJw747WYKUPxQaSYtFKF7IOizJu/8mMj++Zc1dZ5ZP3YQ==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/element-canvas": "^2.1.0", + "@cropper/element-image": "^2.1.0", + "@cropper/element-selection": "^2.1.0", + "@cropper/utils": "^2.1.0" + } + }, + "@cropper/elements": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/elements/-/elements-2.1.0.tgz", + "integrity": "sha512-qvzlYDn3VQgPPpsCu6Gi1XUO0v3vpXQFSjjxcVijbXeNsl/eiKrN7H9/CEiRgi5vr8kXfd7ZvgYxBjUBbH+y+w==", + "requires": { + "@cropper/element": "^2.1.0", + "@cropper/element-canvas": "^2.1.0", + "@cropper/element-crosshair": "^2.1.0", + "@cropper/element-grid": "^2.1.0", + "@cropper/element-handle": "^2.1.0", + "@cropper/element-image": "^2.1.0", + "@cropper/element-selection": "^2.1.0", + "@cropper/element-shade": "^2.1.0", + "@cropper/element-viewer": "^2.1.0" + } + }, + "@cropper/utils": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/@cropper/utils/-/utils-2.1.0.tgz", + "integrity": "sha512-wLtpZ4/UWgo+fGmG8NBWge8x5ehjfDe9ovleDfLy8kpwFaw43XXOEXQtRL1UNr0u4JZxaeO8FcXcolRWUUrlRQ==" + }, "@ctrl/tinycolor": { "version": "3.6.0", "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.0.tgz", @@ -3906,6 +4015,15 @@ "readable-stream": "^3.4.0" } }, + "cropperjs": { + "version": "2.0.0-rc.2", + "resolved": "https://registry.npmmirror.com/cropperjs/-/cropperjs-2.0.0-rc.2.tgz", + "integrity": "sha512-BTuz+UeZphGOEnBCuQiNT4rk1uFfKJaKmTgoH9XU7Q8IMkLdodW7YPWINmXJXwWMt1nXiKze5qKADVbz9xtVFg==", + "requires": { + "@cropper/elements": "^2.0.0-rc.2", + "@cropper/utils": "^2.0.0-rc.2" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", diff --git a/package.json b/package.json index b827103a..30675ccc 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "axios": "^1.1.3", "babel-eslint": "^10.1.0", "core-js": "^3.8.3", + "cropperjs": "^2.0.0-rc.2", "dayjs": "^1.11.6", "echarts": "^5.4.1", "element-plus": "^2.2.17", diff --git a/src/api/modules/xajax.js b/src/api/modules/xajax.js index e1e81807..a440024f 100644 --- a/src/api/modules/xajax.js +++ b/src/api/modules/xajax.js @@ -43,12 +43,13 @@ jsonRequest.interceptors.response.use( { type: "warning", confirmButtonText: "重新登录", + cancelButtonText: "取消", } ).then(() => { window.location.href = ReLoginUrl; }); } else if (code === 403) { - ElMessage.error("当前操作没有权限"); + $message.error("当前操作没有权限"); } else if (code === 302) { window.location.href = ReLoginUrl; } else { @@ -113,6 +114,7 @@ formRequest.interceptors.response.use( ElMessageBox.confirm("登录状态无效,即将跳转至登录页", "登录已过期", { type: "warning", confirmButtonText: "确认", + cancelButtonText: "取消", }).then(() => { window.location.href = ReLoginUrl; }); diff --git a/src/components/Cropper/Cropper.vue b/src/components/Cropper/Cropper.vue new file mode 100644 index 00000000..d740473d --- /dev/null +++ b/src/components/Cropper/Cropper.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/src/views/courselibrary/components/professionalmode.vue b/src/views/courselibrary/components/professionalmode.vue index ba445519..99fb9964 100644 --- a/src/views/courselibrary/components/professionalmode.vue +++ b/src/views/courselibrary/components/professionalmode.vue @@ -16,8 +16,10 @@ import { ElSelectV2, ElTreeSelect, ElOption, + ElDialog, } from "element-plus"; import FieldCloud from "@/components/FileCloud/index.vue"; +import Cropper from "@/components/Cropper/Cropper.vue"; import { useUpload } from "@/hooks/useUpload"; import { useCourseForm } from "@/hooks/useCourseForm"; import { useRouter } from "vue-router"; @@ -66,6 +68,7 @@ const dlgFileShow = ref(false); const chooseFile = () => { dlgFileShow.value = true; }; +const dlgCutShow = ref(false); const changeCourseImage = (img) => { if (!img.path) { @@ -73,12 +76,17 @@ const changeCourseImage = (img) => { } dlgFileShow.value = false; formState.coverImg = fileBaseUrl + img.path; + dlgCutShow.value = true; }; const choseChoose = () => { dlgFileShow.value = false; }; +const success = (e) => { + console.log(e); + formState.coverImg = e; +}; // 表单提交 const handleSubmit = () => { // formRef.value @@ -331,6 +339,13 @@ onMounted(() => { @choose="changeCourseImage" @close="choseChoose" > + + +