Commit 6a94a83d27b8402297500a3177910b6c6e5f85d1

Authored by 杨泽宇
1 parent 0ab68841

单图片上传组件

src/components/Pagination/index.vue
1 <script setup lang="ts"> 1 <script setup lang="ts">
2 /** 2 /**
3 - * 单个图片上传公共组件 3 + * 分页
4 * @module Pagination 4 * @module Pagination
5 */ 5 */
6 6
src/components/Uploader/index.vue 0 → 100644
  1 +<script setup lang="ts">
  2 +/**
  3 + * 单个图片上传公共组件
  4 + * @module Pagination
  5 + */
  6 +import { ref, reactive } from "vue";
  7 +import * as store from "@/pinia/index";
  8 +import { ElMessage } from "element-plus";
  9 +import { Plus } from "@element-plus/icons-vue";
  10 +import type {
  11 + ElUploadProgressEvent,
  12 + ElFile,
  13 +} from "element-plus/es/components/upload/src/upload.type";
  14 +/**
  15 + * @description 组件属性
  16 + * @prop {string | null} tagName 标签
  17 + * @prop {number | null} maxSize 允许上传的最大图片尺寸 default = 1 means 1MB
  18 + * @prop {array<string>} formats 允许上传的图片格式
  19 + * @prop {string | null} defaultUrl 默认图片
  20 + * @prop {string | null} moduleName 上传接口需要传的module值
  21 + * @prop {string | null} showType 组件类型,横图=horizontal(4:3),竖图=vertical(3:4),正图=square(1:1),小正图=mini(1:1),default=null=""=horizontal
  22 + * @prop {string} tip 上传须知
  23 + */
  24 +interface Props {
  25 + tagName: string;
  26 + maxSize?: number;
  27 + formats?: string[];
  28 + defaultUrl?: object;
  29 + showType?: string;
  30 + moduleName?: string;
  31 + tip?: string;
  32 +}
  33 +const props = withDefaults(defineProps<Props>(), {
  34 + formats: () => [
  35 + "image/jpeg",
  36 + "image/gif",
  37 + "image/png",
  38 + "image/x-icon",
  39 + "image/svg+xml",
  40 + "image/webp",
  41 + ],
  42 + maxSize: 1,
  43 + defaultUrl: {
  44 + type: Object,
  45 + default: {
  46 + value: ''
  47 + }
  48 + },
  49 + showType: "horizontal",
  50 + moduleName: "test",
  51 + tip: "支持16:9 的图片,建议最佳尺寸:750*422,大小不能超过500KB",
  52 +});
  53 +/**
  54 + * @description 上传图片接口配置
  55 + */
  56 +const uploadSettings = reactive({
  57 + uploadUrl: `${import.meta.env.VITE_BASE_URL}upload/uploadPicSource?module=${
  58 + props.moduleName
  59 + }`,
  60 + headers: {
  61 + type: "formData",
  62 + "X-Token": store.family.loginStore().token,
  63 + },
  64 +});
  65 +/**
  66 + * @method handleAvatarSuccess
  67 + * @description 图片上传成功
  68 + * @param {object} res 接口返回信息
  69 + */
  70 +const handleAvatarSuccess = (res: ElUploadProgressEvent) => {
  71 + ElMessage.success("图片上传成功");
  72 + props.defaultUrl.value = res?.data;
  73 + emit("imageChange", res?.data, props.tagName);
  74 +};
  75 +/**
  76 + * @method beforeAvatarUpload
  77 + * @description 图片上传之前检查格式、最大尺寸
  78 + * @param {ElFile} file 文件对象
  79 + */
  80 +const beforeAvatarUpload = (file: ElFile) => {
  81 + const isFormatAllowed = props.formats.includes(file.type);
  82 + const isSizeAllowed = file.size / 1024 / 1024 < props.maxSize;
  83 + if (!isFormatAllowed) {
  84 + ElMessage.error("图片格式不支持");
  85 + }
  86 + if (!isSizeAllowed) {
  87 + ElMessage.error("图片尺寸过大");
  88 + }
  89 + return isFormatAllowed && isSizeAllowed;
  90 +};
  91 +const emit = defineEmits<{
  92 + (e: "imageChange", url: string, tagName: string): void;
  93 +}>();
  94 +</script>
  95 +
  96 +<template>
  97 + <div class="uploader-container">
  98 + <el-upload
  99 + class="avatar-uploader"
  100 + :with-credentials="true"
  101 + :show-file-list="false"
  102 + :action="uploadSettings.uploadUrl"
  103 + :headers="uploadSettings.headers"
  104 + name="multipartFile"
  105 + :on-success="handleAvatarSuccess"
  106 + :before-upload="beforeAvatarUpload"
  107 + >
  108 + <img
  109 + v-if="props.defaultUrl.value"
  110 + :src="props.defaultUrl.value"
  111 + class="avatar"
  112 + :class="props.showType"
  113 + />
  114 + <el-icon v-else class="avatar-uploader-icon" :class="props.showType"
  115 + ><plus
  116 + /></el-icon>
  117 + </el-upload>
  118 + <div class="tip">{{ props.tip }}</div>
  119 + </div>
  120 +</template>
  121 +
  122 +<style scoped lang="scss">
  123 +.avatar-uploader .el-upload {
  124 + border: 1px dashed #d9d9d9;
  125 + border-radius: 6px;
  126 + cursor: pointer;
  127 + position: relative;
  128 + overflow: hidden;
  129 +}
  130 +.avatar-uploader .el-upload:hover {
  131 + border-color: #409eff;
  132 +}
  133 +.avatar-uploader-icon {
  134 + font-size: 28px;
  135 + color: #8c939d;
  136 + text-align: center;
  137 + border: 1px dashed #d9d9d9;
  138 +}
  139 +.avatar {
  140 + display: block;
  141 +}
  142 +.tip {
  143 + color: #606266;
  144 + font-size: 12px;
  145 +}
  146 +
  147 +.square {
  148 + width: 178px;
  149 + height: 178px;
  150 + line-height: 178px;
  151 +}
  152 +.mini {
  153 + width: 90px;
  154 + height: 90px;
  155 + line-height: 90px;
  156 +}
  157 +.horizontal {
  158 + width: 180px;
  159 + height: 135px;
  160 + line-height: 135px;
  161 +}
  162 +.vertical {
  163 + width: 135px;
  164 + height: 180px;
  165 + line-height: 180px;
  166 +}
  167 +</style>
src/views/property/edit.vue
@@ -2,8 +2,9 @@ @@ -2,8 +2,9 @@
2 import { reactive, ref, getCurrentInstance, onMounted } from "vue"; 2 import { reactive, ref, getCurrentInstance, onMounted } from "vue";
3 import { propertyAdd } from "@/api/property"; 3 import { propertyAdd } from "@/api/property";
4 import { useRoute } from "vue-router"; 4 import { useRoute } from "vue-router";
5 -import { back } from '@/utils/tool'; 5 +import { back } from "@/utils/tool";
6 import { validMobile } from "@/utils/validate"; 6 import { validMobile } from "@/utils/validate";
  7 +import Uploader from "@/components/Uploader/index.vue";
7 import type { ElForm } from "element-plus"; 8 import type { ElForm } from "element-plus";
8 const { 9 const {
9 appContext: { 10 appContext: {
@@ -27,6 +28,9 @@ let form = reactive({ @@ -27,6 +28,9 @@ let form = reactive({
27 status: 0, 28 status: 0,
28 }, 29 },
29 }); 30 });
  31 +const handleImageChange = (url: string, tagName: string) => {
  32 + form.data[tagName] = url;
  33 +};
30 const ruleFormRef = ref<InstanceType<typeof ElForm>>(); 34 const ruleFormRef = ref<InstanceType<typeof ElForm>>();
31 /** 35 /**
32 * 手机号校验 36 * 手机号校验
@@ -187,11 +191,7 @@ onMounted(() =&gt; { @@ -187,11 +191,7 @@ onMounted(() =&gt; {
187 placeholder="请选择地区" 191 placeholder="请选择地区"
188 clearable 192 clearable
189 > 193 >
190 - <el-option  
191 - label="北京"  
192 - value="北京"  
193 - >  
194 - </el-option> 194 + <el-option label="北京" value="北京"> </el-option>
195 </el-select> 195 </el-select>
196 </el-form-item> 196 </el-form-item>
197 <el-form-item label="详细地址" prop="address" style="width: 100%"> 197 <el-form-item label="详细地址" prop="address" style="width: 100%">
@@ -206,18 +206,18 @@ onMounted(() =&gt; { @@ -206,18 +206,18 @@ onMounted(() =&gt; {
206 prop="businessLicense" 206 prop="businessLicense"
207 style="width: 50%" 207 style="width: 50%"
208 > 208 >
209 - <el-input  
210 - v-model.trim="form.data.businessLicense"  
211 - placeholder="请填写营业执照"  
212 - maxlength="1500"  
213 - /> 209 + <Uploader
  210 + :defaultUrl="{ value: form.data.businessLicense }"
  211 + tagName="businessLicense"
  212 + @imageChange="handleImageChange"
  213 + ></Uploader>
214 </el-form-item> 214 </el-form-item>
215 <el-form-item label="物业LOGO" prop="logo" style="width: 50%"> 215 <el-form-item label="物业LOGO" prop="logo" style="width: 50%">
216 - <el-input  
217 - v-model.trim="form.data.logo"  
218 - placeholder="请填写物业LOGO"  
219 - maxlength="1500"  
220 - /> 216 + <Uploader
  217 + :defaultUrl="{ value: form.data.logo }"
  218 + tagName="logo"
  219 + @imageChange="handleImageChange"
  220 + ></Uploader>
221 </el-form-item> 221 </el-form-item>
222 <el-form-item label="合同编号" prop="contractNumber" style="width: 50%"> 222 <el-form-item label="合同编号" prop="contractNumber" style="width: 50%">
223 <el-input 223 <el-input
@@ -234,7 +234,10 @@ onMounted(() =&gt; { @@ -234,7 +234,10 @@ onMounted(() =&gt; {
234 /> 234 />
235 </el-form-item> 235 </el-form-item>
236 <el-form-item label="类型" prop="type" style="width: 50%"> 236 <el-form-item label="类型" prop="type" style="width: 50%">
237 - <el-select v-model="form.data.type" :disabled="form.dataType === 'edit'"> 237 + <el-select
  238 + v-model="form.data.type"
  239 + :disabled="form.dataType === 'edit'"
  240 + >
238 <el-option label="物业" value="1"></el-option> 241 <el-option label="物业" value="1"></el-option>
239 <el-option label="公益" value="2"></el-option> 242 <el-option label="公益" value="2"></el-option>
240 </el-select> 243 </el-select>
@@ -246,9 +249,7 @@ onMounted(() =&gt; { @@ -246,9 +249,7 @@ onMounted(() =&gt; {
246 <el-button type="info" @click="resetForm(ruleFormRef)" 249 <el-button type="info" @click="resetForm(ruleFormRef)"
247 >取消</el-button 250 >取消</el-button
248 > 251 >
249 - <el-button type="info" @click="back"  
250 - >返回</el-button  
251 - > 252 + <el-button type="info" @click="back">返回</el-button>
252 </el-form-item> 253 </el-form-item>
253 </el-form> 254 </el-form>
254 </el-card> 255 </el-card>