feat: ✨ 添加单图上传组件和使用示例
This commit is contained in:
163
src/components/Upload/SingleImageUpload.vue
Normal file
163
src/components/Upload/SingleImageUpload.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<!-- 单图上传组件 -->
|
||||
<template>
|
||||
<el-upload
|
||||
v-model="imgUrl"
|
||||
class="img-upload"
|
||||
:show-file-list="false"
|
||||
list-type="picture-card"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:http-request="uploadFile"
|
||||
:style="{ width: props.size, height: props.size }"
|
||||
:accept="props.accept"
|
||||
>
|
||||
<template #default>
|
||||
<el-image v-if="imgUrl" :src="imgUrl" />
|
||||
|
||||
<div v-if="imgUrl" class="img-upload__overlay">
|
||||
<el-icon class="img-upload__preview-icon" @click.stop="handlePreview">
|
||||
<ZoomIn />
|
||||
</el-icon>
|
||||
|
||||
<el-icon class="img-upload__delete-icon" @click.stop="handleDelete">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</div>
|
||||
<el-icon v-else class="img-upload__add-icon">
|
||||
<Plus />
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-upload>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
ElImageViewer,
|
||||
UploadRawFile,
|
||||
UploadRequestOptions,
|
||||
} from "element-plus";
|
||||
import FileAPI from "@/api/file";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
maxSize: {
|
||||
type: Number,
|
||||
default: 10, // 默认限制为 10MB
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: "150px",
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["update:modelValue"]);
|
||||
const imgUrl = defineModel("modelValue", {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "",
|
||||
});
|
||||
|
||||
/**
|
||||
* 自定义图片上传
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
async function uploadFile(options: UploadRequestOptions): Promise<any> {
|
||||
const data = await FileAPI.upload(options.file);
|
||||
imgUrl.value = data.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 限制用户上传文件的格式和大小
|
||||
*/
|
||||
function handleBeforeUpload(file: UploadRawFile) {
|
||||
if (file.size > props.maxSize * 1024 * 1024) {
|
||||
ElMessage.warning(`上传图片不能大于${props.maxSize}MB`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览图片
|
||||
*/
|
||||
function handlePreview() {
|
||||
if (imgUrl.value) {
|
||||
const imageViewerApp = createApp({
|
||||
setup() {
|
||||
return () =>
|
||||
h(ElImageViewer, {
|
||||
urlList: [imgUrl.value],
|
||||
initialIndex: 0,
|
||||
onClose: () => {
|
||||
imageViewerApp.unmount();
|
||||
document.body.removeChild(container);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
const container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
imageViewerApp.mount(container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除图片
|
||||
*/
|
||||
function handleDelete() {
|
||||
imgUrl.value = "";
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-upload--picture-card) {
|
||||
/* width: var(--el-upload-picture-card-size);
|
||||
height: var(--el-upload-picture-card-size); */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.img-upload {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
border: 1px var(--el-border-color) solid;
|
||||
border-radius: 5px;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
&__delete-icon {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&__overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #fff;
|
||||
background-color: var(--el-overlay-color-lighter);
|
||||
border-radius: 6px;
|
||||
opacity: 0;
|
||||
transition: opacity var(--el-transition-duration);
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
6
src/types/components.d.ts
vendored
6
src/types/components.d.ts
vendored
@@ -66,13 +66,11 @@ declare module "vue" {
|
||||
GithubCorner: (typeof import("./../components/GithubCorner/index.vue"))["default"];
|
||||
Hamburger: (typeof import("./../components/Hamburger/index.vue"))["default"];
|
||||
IconSelect: (typeof import("./../components/IconSelect/index.vue"))["default"];
|
||||
|
||||
LangSelect: (typeof import("./../components/LangSelect/index.vue"))["default"];
|
||||
MenuSearch: (typeof import("./../components/MenuSearch/index.vue"))["default"];
|
||||
Notice: (typeof import("./../components/Notice/index.vue"))["default"];
|
||||
NoticeDetail: (typeof import("../views/system/notice/notice-detail.vue"))["default"];
|
||||
LayoutSelect: (typeof import("./../layout/components/Settings/components/LayoutSelect.vue"))["default"];
|
||||
MultiUpload: (typeof import("./../components/Upload/MultiUpload.vue"))["default"];
|
||||
NavBar: (typeof import("./../layout/components/NavBar/index.vue"))["default"];
|
||||
NavbarAction: (typeof import("./../layout/components/NavBar/components/NavbarAction.vue"))["default"];
|
||||
PageContent: (typeof import("./../components/CURD/PageContent.vue"))["default"];
|
||||
@@ -89,12 +87,14 @@ declare module "vue" {
|
||||
SidebarMenuItem: (typeof import("./../layout/components/Sidebar/components/SidebarMenuItem.vue"))["default"];
|
||||
SidebarMenuItemTitle: (typeof import("./../layout/components/Sidebar/components/SidebarMenuItemTitle.vue"))["default"];
|
||||
SidebarMixTopMenu: (typeof import("./../layout/components/Sidebar/components/SidebarMixTopMenu.vue"))["default"];
|
||||
SingleUpload: (typeof import("./../components/Upload/SingleUpload.vue"))["default"];
|
||||
SizeSelect: (typeof import("./../components/SizeSelect/index.vue"))["default"];
|
||||
SvgIcon: (typeof import("./../components/SvgIcon/index.vue"))["default"];
|
||||
TableSelect: (typeof import("./../components/TableSelect/index.vue"))["default"];
|
||||
TagsView: (typeof import("./../layout/components/TagsView/index.vue"))["default"];
|
||||
ThemeColorPicker: (typeof import("./../layout/components/Settings/components/ThemeColorPicker.vue"))["default"];
|
||||
FileUpload: (typeof import("./../components/Upload/FileUpload.vue"))["default"];
|
||||
ImageUpload: (typeof import("./../components/Upload/ImageUpload.vue"))["default"];
|
||||
SingleImageUpload: (typeof import("./../components/Upload/SingleImageUpload.vue"))["default"];
|
||||
WangEditor: (typeof import("./../components/WangEditor/index.vue"))["default"];
|
||||
}
|
||||
export interface ComponentCustomProperties {
|
||||
|
||||
@@ -2,8 +2,38 @@
|
||||
<script setup lang="ts">
|
||||
import ImageUpload from "@/components/Upload/ImageUpload.vue";
|
||||
import FileUpload from "@/components/Upload/FileUpload.vue";
|
||||
const size = ref("");
|
||||
// 这里放外链图片,防止被删
|
||||
|
||||
// 单图
|
||||
const picUrl = ref("https://s2.loli.net/2023/05/24/yNsxFC8rLHMZQcK.jpg");
|
||||
|
||||
const singleImageUploadArgData = [
|
||||
{
|
||||
argsName: "v-model",
|
||||
type: "String",
|
||||
default: "",
|
||||
desc: "已经上传的图片URL",
|
||||
},
|
||||
{
|
||||
argsName: "size",
|
||||
type: "String",
|
||||
default: "148px",
|
||||
desc: "图片上传组件的尺寸大小",
|
||||
},
|
||||
{
|
||||
argsName: "maxSize",
|
||||
type: "Number",
|
||||
default: "10",
|
||||
desc: "单个图片上传大小限制(单位M)",
|
||||
},
|
||||
{
|
||||
argsName: "accept",
|
||||
type: "String",
|
||||
default: "",
|
||||
desc: "上传文件类型",
|
||||
},
|
||||
];
|
||||
|
||||
// 多图
|
||||
const picUrls = ref([
|
||||
"https://s2.loli.net/2023/05/24/yNsxFC8rLHMZQcK.jpg",
|
||||
"https://s2.loli.net/2023/05/24/RuHFMwW4rG5lIqs.jpg",
|
||||
@@ -11,10 +41,11 @@ const picUrls = ref([
|
||||
"https://s2.loli.net/2023/05/24/e1bcnEq3MFdmlNL.jpg",
|
||||
"https://s2.loli.net/2023/05/24/wZTSPj1yDQNcuhU.jpg",
|
||||
]);
|
||||
|
||||
const imageUploadArgData = [
|
||||
{
|
||||
argsName: "v-model",
|
||||
type: "Arrays",
|
||||
type: "Array",
|
||||
default: "[]",
|
||||
desc: "已经上传的图片数组",
|
||||
},
|
||||
@@ -184,7 +215,19 @@ const fileUploadArgData = [
|
||||
</el-link>
|
||||
|
||||
<el-form>
|
||||
<el-form-item label="图片上传">
|
||||
<el-form-item label="单图上传">
|
||||
<SingleImageUpload v-model="picUrl" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数说明">
|
||||
<el-table :data="singleImageUploadArgData" border>
|
||||
<el-table-column prop="argsName" label="参数名称" width="300" />
|
||||
<el-table-column prop="type" label="参数类型" width="200" />
|
||||
<el-table-column prop="default" label="默认值" width="400" />
|
||||
<el-table-column prop="desc" label="描述" width="300" />
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="多图上传">
|
||||
<image-upload v-model="picUrls" />
|
||||
</el-form-item>
|
||||
<el-form-item label="参数说明">
|
||||
@@ -195,6 +238,7 @@ const fileUploadArgData = [
|
||||
<el-table-column prop="desc" label="描述" width="300" />
|
||||
</el-table>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文件上传">
|
||||
<file-upload v-model="fileUrls" />
|
||||
</el-form-item>
|
||||
|
||||
Reference in New Issue
Block a user