|
@@ -0,0 +1,186 @@
|
|
|
+<!--
|
|
|
+ * @Author: Gui
|
|
|
+ * @Date: 2023-05-12 11:36:28
|
|
|
+ * @LastEditors: guicheng 1625811865@qq.com
|
|
|
+ * @LastEditTime: 2024-06-20 16:14:29
|
|
|
+ * @Description: kxs files
|
|
|
+ * @filePath:
|
|
|
+-->
|
|
|
+<template lang="pug">
|
|
|
+el-upload(
|
|
|
+ref="uploadRef"
|
|
|
+v-model:file-list="fileList"
|
|
|
+action="http://oss.kexiaoshuang.com"
|
|
|
+list-type="picture-card"
|
|
|
+:on-change="onChange"
|
|
|
+:auto-upload="false"
|
|
|
+:on-preview="handlePictureCardPreview"
|
|
|
+:on-remove="handleRemove"
|
|
|
+:limit="props.limit"
|
|
|
+)
|
|
|
+ IconifyIconOnline( icon="material-symbols:add-rounded" width="60px" height="60px" style="margin:0 auto;color:#999")
|
|
|
+ template(#tip)
|
|
|
+ .el-upload__tip.text-red 最多上传{{props.limit}}张图片
|
|
|
+el-dialog( v-model="dialogVisible" title="图片预览" width="80%" draggable :destroy-on-close="true")
|
|
|
+ div(class="flex justify-center align-middle" )
|
|
|
+ img.preview(w-full :src="dialogImageUrl" alt="Preview Image" style="width:100%;height:100%;")
|
|
|
+
|
|
|
+el-dialog(v-model="clipPhoto" title="裁剪图片" :destroy-on-close="true" draggable width="30vw")
|
|
|
+
|
|
|
+ ReCropper(
|
|
|
+ ref="refCropper"
|
|
|
+ class="w-[30vw] h-[30vh]"
|
|
|
+ :src="selectImg"
|
|
|
+ :options={aspectRatio:aspectRatio}
|
|
|
+ )
|
|
|
+ template( #footer="")
|
|
|
+ .flex
|
|
|
+ el-button( @click="clipPhoto = false") 取消
|
|
|
+ el-button( type="primary" @click="confirmAdd") 确定
|
|
|
+
|
|
|
+</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+import { getConfig } from "@/config";
|
|
|
+import { ref, nextTick, onMounted, watch } from "vue";
|
|
|
+import Ossupload from "@/utils/OSSupload";
|
|
|
+import type { UploadProps, UploadUserFile } from "element-plus";
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+import ReCropper from "@/components/ReCropper";
|
|
|
+
|
|
|
+type Res = {
|
|
|
+ uploadurl?: string; // 上传地址
|
|
|
+ url?: string; // 上传地址(+域名)
|
|
|
+};
|
|
|
+const props = defineProps({
|
|
|
+ limit: {
|
|
|
+ type: Number,
|
|
|
+ default: 1
|
|
|
+ },
|
|
|
+ cropper: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ callBack: {
|
|
|
+ type: Function,
|
|
|
+ default: () => { }
|
|
|
+ },
|
|
|
+ imgList: {
|
|
|
+ type: Object,
|
|
|
+ default: []
|
|
|
+ },
|
|
|
+
|
|
|
+});
|
|
|
+onMounted(() => {
|
|
|
+ console.log(props.imgList, 12312)
|
|
|
+ if (props.imgList && props.imgList.length > 0) {
|
|
|
+ props.imgList.forEach(item => {
|
|
|
+ fileList.value.push({ name: "1", url: item });
|
|
|
+ UrlList.value.push(item.split(getConfig().UploadUrl + '/')[1]);
|
|
|
+ })
|
|
|
+ }
|
|
|
+ console.log(fileList.value, 'fileList', UrlList.value)
|
|
|
+})
|
|
|
+// watch(
|
|
|
+// () => props.imgList,
|
|
|
+// newValue => {
|
|
|
+// console.log(newValue)
|
|
|
+// if (newValue) {
|
|
|
+// initImg()
|
|
|
+// newValue.forEach(item => {
|
|
|
+// fileList.value.push({ name: "1", url: item });
|
|
|
+// UrlList.value.push(item.split(getConfig().UploadUrl + '/')[1]);
|
|
|
+// })
|
|
|
+// } else {
|
|
|
+// initImg()
|
|
|
+// }
|
|
|
+// console.log(fileList.value, 'fileList', UrlList.value)
|
|
|
+// }
|
|
|
+// );
|
|
|
+const aspectRatio = ref(1);
|
|
|
+// 文件列表
|
|
|
+const fileList = ref<UploadUserFile[]>([]);
|
|
|
+// 上传路径列表
|
|
|
+const UrlList = ref<UploadUserFile[]>([]);
|
|
|
+// 图片上传、预览、裁剪
|
|
|
+const dialogImageUrl = ref("");
|
|
|
+// 是否预览
|
|
|
+const dialogVisible = ref(false);
|
|
|
+// 是否裁剪图片
|
|
|
+const clipPhoto = ref(false);
|
|
|
+// 裁剪的图片
|
|
|
+const selectImg = ref("");
|
|
|
+// 裁剪之后的图片
|
|
|
+const cropperImgName = ref("");
|
|
|
+const uploadRef = ref();
|
|
|
+const refCropper = ref();
|
|
|
+
|
|
|
+const onChange = (file: any) => {
|
|
|
+ if (
|
|
|
+ file.raw.type == "image/webp" ||
|
|
|
+ file.raw.type == "image/png" ||
|
|
|
+ file.raw.type == "image/jpeg"
|
|
|
+ ) {
|
|
|
+ if (file.status == "ready") {
|
|
|
+ // 裁剪
|
|
|
+ if (props.cropper) {
|
|
|
+ selectImg.value = file!.url;
|
|
|
+ cropperImgName.value = file.name;
|
|
|
+ clipPhoto.value = true;
|
|
|
+ } else {
|
|
|
+ // 直接上传,不需要裁剪
|
|
|
+ OssUp(file.raw);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ ElMessage({
|
|
|
+ message: "仅支持png/jpg/webp 格式的图片文件",
|
|
|
+ type: "error"
|
|
|
+ });
|
|
|
+ }
|
|
|
+ nextTick(() => {
|
|
|
+ uploadRef.value.clearFiles(["ready", "uploading", "fail"]);
|
|
|
+ });
|
|
|
+};
|
|
|
+const handlePictureCardPreview: UploadProps["onPreview"] = uploadFile => {
|
|
|
+ dialogImageUrl.value = uploadFile.url!;
|
|
|
+ dialogVisible.value = true;
|
|
|
+};
|
|
|
+const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
|
|
|
+ fileList.value = uploadFiles;
|
|
|
+ // console.log(uploadFiles, '--删除', uploadFile)
|
|
|
+ let uploadFilesdata = []
|
|
|
+ uploadFiles.forEach((item: any) => {
|
|
|
+ uploadFilesdata.push(item.url.split(getConfig().UploadUrl + '/')[1])
|
|
|
+ })
|
|
|
+ UrlList.value = uploadFilesdata
|
|
|
+};
|
|
|
+const initImg = () => {
|
|
|
+
|
|
|
+ fileList.value = []
|
|
|
+ UrlList.value = []
|
|
|
+ // fileList.value.push({ name: cropperImgName.value, url: res.url });
|
|
|
+ // UrlList.value.push(res.uploadurl);
|
|
|
+
|
|
|
+}
|
|
|
+const confirmAdd = (): void => {
|
|
|
+ nextTick(() => {
|
|
|
+ refCropper.value.cropper.getCroppedCanvas().toBlob(blob => {
|
|
|
+ // upload to oss
|
|
|
+ const file = new File([blob], cropperImgName.value, {
|
|
|
+ type: "image/png"
|
|
|
+ });
|
|
|
+ OssUp(file);
|
|
|
+ }, "image/jpeg");
|
|
|
+ clipPhoto.value = false;
|
|
|
+ });
|
|
|
+};
|
|
|
+const OssUp = file => {
|
|
|
+ Ossupload(file, "KxsAdmin/UploadImg").then((res: Res) => {
|
|
|
+ fileList.value.push({ name: cropperImgName.value, url: res.url });
|
|
|
+ UrlList.value.push(res.uploadurl);
|
|
|
+
|
|
|
+
|
|
|
+ props.callBack(UrlList.value.join(","));
|
|
|
+ });
|
|
|
+};
|
|
|
+</script>
|