From f2138817fdd6e9141c5911514280b8d0b6ca08f1 Mon Sep 17 00:00:00 2001 From: hcong <1050828145@qq.com> Date: 星期三, 20 十一月 2024 14:48:49 +0800 Subject: [PATCH] 子组件刷新父组件不刷新页面,表单验证,upload组件预览图片,弹窗放在组件内部,bug修复 --- src/components/FYImageSelectDialog.vue | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 206 insertions(+), 22 deletions(-) diff --git a/src/components/FYImageSelectDialog.vue b/src/components/FYImageSelectDialog.vue index f9f249c..99397d4 100644 --- a/src/components/FYImageSelectDialog.vue +++ b/src/components/FYImageSelectDialog.vue @@ -1,23 +1,24 @@ <template> <el-dialog - v-model="anyPhotoDialog" + :model-value="dialogVisible" + @opened="$emit('update:dialogVisible', true)" + @closed="$emit('update:dialogVisible', false)" width="66%" - title="浠绘剰鍥剧墖" destroy-on-close > - <div class="main"> - <el-row justify="end" class="btns" v-if="!readonly"> + <div class="main" v-loading="loading"> + <el-row justify="end" v-if="!readonly"> <el-text size="small" type="info" class="m-r-8" >鏈�澶氶�夋嫨{{ maxSelect }}寮犲浘鐗�</el-text > <el-button size="small" type="primary" - @click="sendSelectedImg(true)" + @click="handleSubmit" :disabled="selectedImgUrlList.length == 0" >纭畾</el-button > - <el-button size="small" type="primary" @click="sendSelectedImg(false)" + <el-button size="small" type="primary" @click="handleCancel" >鍙栨秷</el-button > </el-row> @@ -28,35 +29,50 @@ v-for="item in typeList" :key="item.typeId" :label=" - item.typeName + ' (' + typeImgMap.get(activeId).length + ')' + item.typeName + ' (' + typeImgMap.get(item.typeId).length + ')' " :name="item.typeId" > </el-tab-pane> </el-tabs> - <el-empty v-if="isEmpty" description="鏆傛棤璁板綍" /> - <el-scrollbar class="imgs"> + <el-scrollbar + v-if="typeImgMap.get(activeId) && typeImgMap.get(activeId).length > 0" + class="imgs" + > <el-image v-for="(img, i) in typeImgMap.get(activeId)" :key="i" :class="[img.isSelect ? 'selected' : 'noActive', 'image']" fit="cover" :src="img.url" - lazy @click="onSelect(img, i)" + @load="onOneImgLoadSuccess" + @error="onOneImgLoadError" /> </el-scrollbar> + <el-row v-else justify="space-between"> + <el-empty description="鏆傛棤璁板綍" /> + </el-row> </div> </div> </el-dialog> </template> <script setup> -import { ref, watch } from 'vue'; +import { ref, watch, computed } from 'vue'; const props = defineProps({ + dialogVisible: Boolean, + /** + * 鍥剧墖鍒嗙被 + * 缁撴瀯{ typeId, typeName } + */ typeList: { type: Array, default: () => [] + }, + typeImgMap: { + type: Array, + default: () => new Map() }, // 鏄惁浠ュ彧璇荤殑褰㈠紡鏌ョ湅褰撳墠椤甸潰 readonly: { @@ -74,26 +90,194 @@ } }); -const activeId = ref(''); -const typeImgMap = ref(new Map()); -const selectedImgList = ref([]); +const emit = defineEmits(['submit', 'cancel', 'update:dialogVisible']); -watch(typeImgMap, (newMap, oldMap) => { - if (newMap.get(activeId.value) == undefined) { +const activeId = ref(''); +// const typeImgMap = ref(new Map()); +const selectedImgUrlList = ref([]); + +let loadedImgCount = ref(0); +// 鍔犺浇鐘舵�� +const loading = computed(() => { + if (activeId.value == '') { + return false; + } + // 淇濊瘉鏈�寮�濮嬫槸鍔犺浇鐘舵�侊紝涓夊垎涔嬩竴鍔犺浇涔嬪悗鍋滄灞曠ず鍔犺浇鐘舵�� + return !( + props.typeImgMap.get(activeId.value).length / 3 <= + loadedImgCount.value + ); +}); +function onOneImgLoadError(e) { + loadedImgCount.value++; +} +function onOneImgLoadSuccess(e) { + loadedImgCount.value++; +} +watch( + () => activeId.value, + (nV, oV) => { + loadedImgCount.value = 0; + }, + { immediate: true } +); + +function onSelect(img, i) { + if (props.readonly) { return; } - newMap.get(activeId.value).forEach( - (i) => { + const imgList = selectedImgUrlList.value; + const index = imgList.indexOf(img); + if (index == -1) { + if (props.maxSelect == 1) { + img.isSelect = true; + imgList.push(img); + if (imgList.length > 1) { + imgList.splice(0, 1).forEach((e) => { + e.isSelect = false; + }); + } + } else if (props.maxSelect > 1) { + if (imgList.length < props.maxSelect) { + img.isSelect = true; + imgList.push(img); + } + } + } else { + imgList.splice(index, 1); + img.isSelect = false; + } +} + +function handleSubmit() { + emit('submit', selectedImgUrlList.value); + emit('update:dialogVisible', false); +} + +function handleCancel() { + emit('cancel'); + emit('update:dialogVisible', false); +} + +watch( + () => props.typeList, + (nV, oV) => { + if (nV != oV && nV.length > 0) { + activeId.value = nV[0].typeId; + } + }, + { immediate: true } +); + +watch( + () => props.typeImgMap, + (newMap, oldMap) => { + if (newMap.get(activeId.value) == undefined) { + return; + } + newMap.get(activeId.value).forEach((i) => { if (i.isSelect == true) { return; } props.defaultFile.forEach((imgItem) => { if (imgItem.url == i.url) { i.isSelect = true; + selectedImgUrlList.value.push(i); } }); - }, - { deep: true } - ); -}); + }); + }, + { deep: true, immediate: true } +); </script> +<style scoped> +.center { + display: flex; + flex-direction: column; + align-items: center; +} +.text { + padding: 20px; +} + +.main { + margin: 0 auto; /* 浣跨埗鍏冪礌灞呬腑 */ + height: 72vh; + width: 100%; +} + +.imgs { + height: 60vh; + width: 100%; + min-height: 100px !important; + /* border-style:solid; + border-radius: 1px; */ + /* height: 100%; */ + flex-grow: 1 !important; + overflow-y: auto !important; + /* 鍐呭鐨勫唴杈硅窛 */ + display: flex !important; + flex-wrap: wrap !important; + /* overflow: hidden; */ +} + +.image { + margin: 5px; + height: 210px; + width: 200px; + border-radius: 4px; +} + +.active { + padding: 5px; + width: 20%; + height: 200px; + border: 0.5rem outset rgb(52, 155, 4); +} + +.selected { + margin: 3px; + color: #4abe84; + box-shadow: 0 2px 7px 0 rgba(85, 110, 97, 0.35); + border: 2px solid rgba(74, 190, 132, 1); +} + +.selected:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + border: 17px solid #4abe84; + border-top-color: transparent; + border-left-color: transparent; +} + +.selected:after { + content: ''; + width: 5px; + height: 12px; + position: absolute; + right: 6px; + bottom: 6px; + border: 2px solid #fff; + border-top-color: transparent; + border-left-color: transparent; + transform: rotate(45deg); +} + +.noActive { + /* padding: 5px; */ +} + +.blurry { + filter: blur(3px); +} +.filters { + display: flex; + padding: 5px; +} + +::v-deep .el-dialog__body { + padding: 10px calc(var(--el-dialog-padding-primary) + 10px) !important; +} +</style> -- Gitblit v1.9.3