perf: 优化图片选择器

This commit is contained in:
kuaifan 2024-11-12 20:30:54 +08:00
parent 6e0a575da9
commit 02d6dcd592
6 changed files with 395 additions and 321 deletions

View File

@ -2,15 +2,15 @@
<EDropdown <EDropdown
ref="dropdown" ref="dropdown"
trigger="click" trigger="click"
class="task-operation-dropdown" class="general-operation-dropdown"
placement="bottom" placement="bottom"
size="small" size="small"
:style="styles" :style="styles"
@command="onCommand" @command="onCommand"
@visible-change="visibleChange"> @visible-change="visibleChange">
<div ref="icon" class="task-operation-icon"></div> <div ref="icon" class="general-operation-icon"></div>
<EDropdownMenu ref="dropdownMenu" slot="dropdown" class="task-operation-more-dropdown"> <EDropdownMenu ref="dropdownMenu" slot="dropdown" class="general-operation-more-dropdown menu-dropdown">
<li class="task-operation-more-warp small"> <li class="general-operation-more-warp small">
<ul> <ul>
<EDropdownItem <EDropdownItem
v-for="(item, key) in list" v-for="(item, key) in list"
@ -73,8 +73,8 @@ export default {
this.scrollHide = typeof data.scrollHide === "boolean" ? data.scrollHide : false; this.scrollHide = typeof data.scrollHide === "boolean" ? data.scrollHide : false;
// //
this.$refs.icon.focus(); this.$refs.icon.focus();
this.updatePopper();
this.show(); this.show();
this.updatePopper();
this.setupEventListeners(data.event) this.setupEventListeners(data.event)
} else { } else {
this.hide() this.hide()
@ -103,7 +103,9 @@ export default {
}, },
updatePopper() { updatePopper() {
this.$nextTick(this.$refs.dropdownMenu.updatePopper) setTimeout(() => {
this.$refs.dropdownMenu.updatePopper();
}, 0);
}, },
setupEventListeners(event) { setupEventListeners(event) {

View File

@ -2,7 +2,7 @@
<div class="common-img-update"> <div class="common-img-update">
<div v-if="type !== 'callback'" class="imgcomp-upload-list" v-for="item in uploadList"> <div v-if="type !== 'callback'" class="imgcomp-upload-list" v-for="item in uploadList">
<template v-if="item.status === 'finished'"> <template v-if="item.status === 'finished'">
<div class="imgcomp-upload-img" v-bind:style="{ 'background-image': 'url(' + backgroundImage(item.thumb) + ')' }"></div> <div @click="handleTouch($event, item)" class="imgcomp-upload-img" v-bind:style="{ 'background-image': 'url(' + backgroundImage(item.thumb) + ')' }"></div>
<div class="imgcomp-upload-list-cover"> <div class="imgcomp-upload-list-cover">
<Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon> <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>
<Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon> <Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon>
@ -13,7 +13,7 @@
</template> </template>
</div> </div>
<div class="add-box" v-bind:class="{ 'callback-add-box': type === 'callback' }"> <div class="add-box" v-bind:class="{ 'callback-add-box': type === 'callback' }">
<div class="add-box-icon"> <div @click="handleTouch($event, null)" class="add-box-icon">
<Icon type="md-add" size="32"></Icon> <Icon type="md-add" size="32"></Icon>
</div> </div>
<div class="add-box-upload"> <div class="add-box-upload">
@ -77,21 +77,17 @@
</template> </template>
<script> <script>
export default { import {languageList} from "../language";
export default {
name: 'ImgUpload', name: 'ImgUpload',
props: { props: {
value: { value: {},
}, num: {},
num: { width: {},
}, height: {},
width: { whcut: {},
}, type: {},
height: {
},
whcut: {
},
type: {
},
http: { http: {
type: Boolean, type: Boolean,
default: false default: false
@ -107,7 +103,7 @@
default: 0 default: 0
} }
}, },
data () { data() {
return { return {
actionUrl: $A.apiUrl('system/imgupload'), actionUrl: $A.apiUrl('system/imgupload'),
multiple: this.num > 1, multiple: this.num > 1,
@ -125,16 +121,16 @@
maxSize: 2048 maxSize: 2048
} }
}, },
mounted () { mounted() {
this.uploadList = this.$refs.upload.fileList; this.uploadList = this.$refs.upload.fileList;
this.$emit('input', this.uploadList); this.$emit('input', this.uploadList);
// //
let browseBox = $A(this.$refs.browselistbox); let browseBox = $A(this.$refs.browselistbox);
browseBox.scroll(()=>{ browseBox.scroll(() => {
let nHight = browseBox[0].scrollHeight; let nHight = browseBox[0].scrollHeight;
let nTop = browseBox[0].scrollTop; let nTop = browseBox[0].scrollTop;
let boxHight = browseBox.height(); let boxHight = browseBox.height();
if(nTop + boxHight >= nHight) { if (nTop + boxHight >= nHight) {
// //
if (this.browseListNext.length > 0) { if (this.browseListNext.length > 0) {
let tmpNext = this.browseListNext; let tmpNext = this.browseListNext;
@ -145,7 +141,7 @@
}); });
}, },
watch: { watch: {
value (val) { value(val) {
if (typeof val === 'string') { if (typeof val === 'string') {
this.$emit('input', this.initItems(val)); this.$emit('input', this.initItems(val));
return; return;
@ -189,7 +185,7 @@
this.$emit('on-callback', this.uploadList); this.$emit('on-callback', this.uploadList);
this.$refs.upload.fileList = []; this.$refs.upload.fileList = [];
this.uploadList = this.$refs.upload.fileList; this.uploadList = this.$refs.upload.fileList;
}else if (typeof file === "object") { } else if (typeof file === "object") {
this.$emit('on-callback', [file]); this.$emit('on-callback', [file]);
} }
} }
@ -201,7 +197,7 @@
items = [{'url': items}]; items = [{'url': items}];
} }
let list = []; let list = [];
$A.each(items, (index, item)=>{ $A.each(items, (index, item) => {
if (typeof item === 'string') item = {'url': item}; if (typeof item === 'string') item = {'url': item};
if (item.url) { if (item.url) {
item.active = true; item.active = true;
@ -213,13 +209,64 @@
}); });
return list; return list;
}, },
handleView (item) { handleTouch(event, item) {
if (!this.windowTouch) {
return;
}
const list = [];
if (item === null) {
const subfix = this.type === 'callback' ? '图片' : '';
list.push(...[
{
label: '浏览' + subfix,
value: 'browse'
},
{
label: '上传' + subfix,
value: 'upload'
}
])
} else {
list.push(...[
{
label: '查看',
value: 'view'
},
{
label: '删除',
value: 'trash'
}
])
}
this.$store.state.menuOperation = {
event,
list,
scrollHide: true,
onUpdate: async (act) => {
switch (act) {
case 'browse':
this.browsePicture();
break;
case 'upload':
this.$refs.upload?.handleClick()
break;
case 'view':
this.handleView(item);
break;
case 'trash':
this.handleRemove(item);
break;
}
}
}
},
handleView(item) {
// //
this.$store.dispatch("previewImage", item.url) this.$store.dispatch("previewImage", item.url)
// this.visible = true; // this.visible = true;
// this.imgVisible = item.url; // this.imgVisible = item.url;
}, },
handleRemove (item) { handleRemove(item) {
// //
let fileList = this.$refs.upload.fileList; let fileList = this.$refs.upload.fileList;
this.$refs.upload.fileList.splice(fileList.indexOf(item), 1); this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
@ -232,7 +279,7 @@
this.$emit('update:uploadIng', this.uploadIng + 1); this.$emit('update:uploadIng', this.uploadIng + 1);
} }
}, },
handleSuccess (res, file) { handleSuccess(res, file) {
// //
this.$emit('update:uploadIng', this.uploadIng - 1); this.$emit('update:uploadIng', this.uploadIng - 1);
if (res.ret === 1) { if (res.ret === 1) {
@ -240,7 +287,7 @@
file.path = res.data.path; file.path = res.data.path;
file.thumb = res.data.thumb; file.thumb = res.data.thumb;
this.handleCallback(file); this.handleCallback(file);
}else{ } else {
$A.noticeWarning({ $A.noticeWarning({
title: this.$L('上传失败'), title: this.$L('上传失败'),
desc: this.$L('文件 ' + file.name + ' 上传失败 ' + res.msg), desc: this.$L('文件 ' + file.name + ' 上传失败 ' + res.msg),
@ -253,21 +300,21 @@
// //
this.$emit('update:uploadIng', this.uploadIng - 1); this.$emit('update:uploadIng', this.uploadIng - 1);
}, },
handleFormatError (file) { handleFormatError(file) {
// //
$A.noticeWarning({ $A.noticeWarning({
title: this.$L('文件格式不正确'), title: this.$L('文件格式不正确'),
desc: this.$L('文件 ' + file.name + ' 格式不正确,请上传 jpg、jpeg、webp、gif、png 格式的图片。') desc: this.$L('文件 ' + file.name + ' 格式不正确,请上传 jpg、jpeg、webp、gif、png 格式的图片。')
}); });
}, },
handleMaxSize (file) { handleMaxSize(file) {
// //
$A.noticeWarning({ $A.noticeWarning({
title: this.$L('超出文件大小限制'), title: this.$L('超出文件大小限制'),
desc: this.$L('文件 ' + file.name + ' 太大,不能超过:' + $A.bytesToSize(this.maxSize * 1024)) desc: this.$L('文件 ' + file.name + ' 太大,不能超过:' + $A.bytesToSize(this.maxSize * 1024))
}); });
}, },
handleBeforeUpload () { handleBeforeUpload() {
// //
let check = this.uploadList.length < this.maxNum; let check = this.uploadList.length < this.maxNum;
if (!check && this.uploadList.length == 1) { if (!check && this.uploadList.length == 1) {
@ -325,7 +372,7 @@
} }
if (o < 100) { if (o < 100) {
this.browseList.push(files[o]); this.browseList.push(files[o]);
}else{ } else {
this.browseListNext.push(files[o]); this.browseListNext.push(files[o]);
} }
} }
@ -336,13 +383,13 @@
if (item.type === 'dir') { if (item.type === 'dir') {
// //
this.browsePicture(item.path); this.browsePicture(item.path);
}else if (item.type === 'file') { } else if (item.type === 'file') {
// //
if (item.active) { if (item.active) {
let fileList = this.$refs.upload.fileList; let fileList = this.$refs.upload.fileList;
this.$refs.upload.fileList.splice(fileList.indexOf(item), 1); this.$refs.upload.fileList.splice(fileList.indexOf(item), 1);
item.active = false; item.active = false;
}else{ } else {
if (this.maxNum === 1) { if (this.maxNum === 1) {
for (let i = 0; i < this.browseList.length; i++) { for (let i = 0; i < this.browseList.length; i++) {
this.browseList[i].active = false; this.browseList[i].active = false;
@ -376,7 +423,7 @@
backgroundImage(url) { backgroundImage(url) {
if ($A.strExists(url, "?", false)) { if ($A.strExists(url, "?", false)) {
return $A.mainUrl(url) + "&__thumb=true"; return $A.mainUrl(url) + "&__thumb=true";
}else{ } else {
return $A.mainUrl(url) + "?__thumb=true"; return $A.mainUrl(url) + "?__thumb=true";
} }
}, },
@ -386,5 +433,5 @@
this.browseVisible = false; this.browseVisible = false;
} }
} }
} }
</script> </script>

View File

@ -6,13 +6,13 @@
:disabled="disabled" :disabled="disabled"
:size="size" :size="size"
:style="styles" :style="styles"
class="task-operation-dropdown" class="general-operation-dropdown"
placement="bottom" placement="bottom"
@command="dropTask" @command="dropTask"
@visible-change="visibleChange"> @visible-change="visibleChange">
<div ref="icon" class="task-operation-icon"></div> <div ref="icon" class="general-operation-icon"></div>
<EDropdownMenu ref="dropdownMenu" slot="dropdown" class="task-operation-more-dropdown"> <EDropdownMenu ref="dropdownMenu" slot="dropdown" class="general-operation-more-dropdown">
<li class="task-operation-more-warp" :class="size"> <li class="general-operation-more-warp" :class="size">
<ul> <ul>
<EDropdownItem v-if="!flow" class="load-flow" disabled> <EDropdownItem v-if="!flow" class="load-flow" disabled>
<div class="load-flow-warp"> <div class="load-flow-warp">

View File

@ -45,6 +45,9 @@
left: 0; left: 0;
right: 0; right: 0;
background: rgba(0, 0, 0, .6); background: rgba(0, 0, 0, .6);
flex-direction: row;
align-items: center;
justify-content: center;
} }
.imgcomp-upload-list-cover i { .imgcomp-upload-list-cover i {
@ -74,7 +77,7 @@
} }
.imgcomp-upload-list:hover .imgcomp-upload-list-cover { .imgcomp-upload-list:hover .imgcomp-upload-list-cover {
display: block; display: flex;
} }
.img-upload-foot { .img-upload-foot {
@ -111,10 +114,11 @@
vertical-align: top; vertical-align: top;
.add-box-icon { .add-box-icon {
i { display: flex;
vertical-align: middle; align-items: center;
padding-bottom: 2px; justify-content: center;
} width: 100%;
height: 100%;
} }
.add-box-upload { .add-box-upload {
@ -132,8 +136,12 @@
height: 22px; height: 22px;
line-height: 22px; line-height: 22px;
cursor: pointer; cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
.ivu-upload-drag, .ivu-upload-drag:hover { .ivu-upload-drag,
.ivu-upload-drag:hover {
background: transparent; background: transparent;
border: 0; border: 0;
border-radius: 0; border-radius: 0;
@ -260,3 +268,17 @@
background-color: rgba(255, 255, 255, 0.9); background-color: rgba(255, 255, 255, 0.9);
z-index: 1; z-index: 1;
} }
// 移动端不显示
body.window-touch {
.imgcomp-upload-list:hover .imgcomp-upload-list-cover {
display: none;
}
.add-box:hover {
border-color: #dddee1;
.add-box-upload {
display: none;
}
}
}

View File

@ -4,6 +4,7 @@
@import "dialog-select"; @import "dialog-select";
@import "dialog-wrapper"; @import "dialog-wrapper";
@import "file-content"; @import "file-content";
@import "general-operation";
@import "meeting-manager"; @import "meeting-manager";
@import "project-archived"; @import "project-archived";
@import "project-dialog"; @import "project-dialog";
@ -20,7 +21,6 @@
@import "task-deleted"; @import "task-deleted";
@import "task-detail"; @import "task-detail";
@import "task-menu"; @import "task-menu";
@import "task-operation";
@import "task-priority"; @import "task-priority";
@import "task-move"; @import "task-move";
@import "team-management"; @import "team-management";

View File

@ -1,4 +1,4 @@
.task-operation-dropdown { .general-operation-dropdown {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@ -18,9 +18,9 @@
} }
} }
.task-operation-more-dropdown { .general-operation-more-dropdown {
> li { > li {
&.task-operation-more-warp { &.general-operation-more-warp {
list-style: none; list-style: none;
> ul { > ul {
@ -89,16 +89,19 @@
border-color: rgba($flow-status-start-color, 0.1); border-color: rgba($flow-status-start-color, 0.1);
color: $flow-status-start-color; color: $flow-status-start-color;
} }
&.progress { &.progress {
background-color: rgba($flow-status-progress-color, 0.1); background-color: rgba($flow-status-progress-color, 0.1);
border-color: rgba($flow-status-progress-color, 0.1); border-color: rgba($flow-status-progress-color, 0.1);
color: $flow-status-progress-color; color: $flow-status-progress-color;
} }
&.test { &.test {
background-color: rgba($flow-status-test-color, 0.1); background-color: rgba($flow-status-test-color, 0.1);
border-color: rgba($flow-status-test-color, 0.1); border-color: rgba($flow-status-test-color, 0.1);
color: $flow-status-test-color; color: $flow-status-test-color;
} }
&.end { &.end {
background-color: rgba($flow-status-end-color, 0.1); background-color: rgba($flow-status-end-color, 0.1);
border-color: rgba($flow-status-end-color, 0.1); border-color: rgba($flow-status-end-color, 0.1);