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"];
|
GithubCorner: (typeof import("./../components/GithubCorner/index.vue"))["default"];
|
||||||
Hamburger: (typeof import("./../components/Hamburger/index.vue"))["default"];
|
Hamburger: (typeof import("./../components/Hamburger/index.vue"))["default"];
|
||||||
IconSelect: (typeof import("./../components/IconSelect/index.vue"))["default"];
|
IconSelect: (typeof import("./../components/IconSelect/index.vue"))["default"];
|
||||||
|
|
||||||
LangSelect: (typeof import("./../components/LangSelect/index.vue"))["default"];
|
LangSelect: (typeof import("./../components/LangSelect/index.vue"))["default"];
|
||||||
MenuSearch: (typeof import("./../components/MenuSearch/index.vue"))["default"];
|
MenuSearch: (typeof import("./../components/MenuSearch/index.vue"))["default"];
|
||||||
Notice: (typeof import("./../components/Notice/index.vue"))["default"];
|
Notice: (typeof import("./../components/Notice/index.vue"))["default"];
|
||||||
NoticeDetail: (typeof import("../views/system/notice/notice-detail.vue"))["default"];
|
NoticeDetail: (typeof import("../views/system/notice/notice-detail.vue"))["default"];
|
||||||
LayoutSelect: (typeof import("./../layout/components/Settings/components/LayoutSelect.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"];
|
NavBar: (typeof import("./../layout/components/NavBar/index.vue"))["default"];
|
||||||
NavbarAction: (typeof import("./../layout/components/NavBar/components/NavbarAction.vue"))["default"];
|
NavbarAction: (typeof import("./../layout/components/NavBar/components/NavbarAction.vue"))["default"];
|
||||||
PageContent: (typeof import("./../components/CURD/PageContent.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"];
|
SidebarMenuItem: (typeof import("./../layout/components/Sidebar/components/SidebarMenuItem.vue"))["default"];
|
||||||
SidebarMenuItemTitle: (typeof import("./../layout/components/Sidebar/components/SidebarMenuItemTitle.vue"))["default"];
|
SidebarMenuItemTitle: (typeof import("./../layout/components/Sidebar/components/SidebarMenuItemTitle.vue"))["default"];
|
||||||
SidebarMixTopMenu: (typeof import("./../layout/components/Sidebar/components/SidebarMixTopMenu.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"];
|
SizeSelect: (typeof import("./../components/SizeSelect/index.vue"))["default"];
|
||||||
SvgIcon: (typeof import("./../components/SvgIcon/index.vue"))["default"];
|
SvgIcon: (typeof import("./../components/SvgIcon/index.vue"))["default"];
|
||||||
TableSelect: (typeof import("./../components/TableSelect/index.vue"))["default"];
|
TableSelect: (typeof import("./../components/TableSelect/index.vue"))["default"];
|
||||||
TagsView: (typeof import("./../layout/components/TagsView/index.vue"))["default"];
|
TagsView: (typeof import("./../layout/components/TagsView/index.vue"))["default"];
|
||||||
ThemeColorPicker: (typeof import("./../layout/components/Settings/components/ThemeColorPicker.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"];
|
WangEditor: (typeof import("./../components/WangEditor/index.vue"))["default"];
|
||||||
}
|
}
|
||||||
export interface ComponentCustomProperties {
|
export interface ComponentCustomProperties {
|
||||||
|
|||||||
@@ -2,8 +2,38 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import ImageUpload from "@/components/Upload/ImageUpload.vue";
|
import ImageUpload from "@/components/Upload/ImageUpload.vue";
|
||||||
import FileUpload from "@/components/Upload/FileUpload.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([
|
const picUrls = ref([
|
||||||
"https://s2.loli.net/2023/05/24/yNsxFC8rLHMZQcK.jpg",
|
"https://s2.loli.net/2023/05/24/yNsxFC8rLHMZQcK.jpg",
|
||||||
"https://s2.loli.net/2023/05/24/RuHFMwW4rG5lIqs.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/e1bcnEq3MFdmlNL.jpg",
|
||||||
"https://s2.loli.net/2023/05/24/wZTSPj1yDQNcuhU.jpg",
|
"https://s2.loli.net/2023/05/24/wZTSPj1yDQNcuhU.jpg",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const imageUploadArgData = [
|
const imageUploadArgData = [
|
||||||
{
|
{
|
||||||
argsName: "v-model",
|
argsName: "v-model",
|
||||||
type: "Arrays",
|
type: "Array",
|
||||||
default: "[]",
|
default: "[]",
|
||||||
desc: "已经上传的图片数组",
|
desc: "已经上传的图片数组",
|
||||||
},
|
},
|
||||||
@@ -184,7 +215,19 @@ const fileUploadArgData = [
|
|||||||
</el-link>
|
</el-link>
|
||||||
|
|
||||||
<el-form>
|
<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" />
|
<image-upload v-model="picUrls" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="参数说明">
|
<el-form-item label="参数说明">
|
||||||
@@ -195,6 +238,7 @@ const fileUploadArgData = [
|
|||||||
<el-table-column prop="desc" label="描述" width="300" />
|
<el-table-column prop="desc" label="描述" width="300" />
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="文件上传">
|
<el-form-item label="文件上传">
|
||||||
<file-upload v-model="fileUrls" />
|
<file-upload v-model="fileUrls" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
Reference in New Issue
Block a user