perf: 优化长按菜单

This commit is contained in:
kuaifan 2025-04-17 09:46:57 +08:00
parent 8f2f68dffc
commit ab616c5d32
9 changed files with 77 additions and 79 deletions

View File

@ -155,7 +155,12 @@
</ul>
</div>
</Scrollbar>
<div class="operate-position" :style="operateStyles" v-show="operateVisible">
<div
v-transfer-dom
:data-transfer="true"
class="operate-position"
:style="operateStyles"
v-show="operateVisible">
<Dropdown
trigger="custom"
:placement="windowLandscape ? 'bottom' : 'top'"
@ -356,6 +361,7 @@ import MobileTabbar from "../components/Mobile/Tabbar";
import TaskAdd from "./manage/components/TaskAdd";
import Report from "./manage/components/Report";
import longpress from "../directives/longpress";
import TransferDom from "../directives/transfer-dom";
import DialogModal from "./manage/components/DialogModal";
import TaskModal from "./manage/components/TaskModal";
import CheckinExport from "./manage/components/CheckinExport";
@ -391,7 +397,7 @@ export default {
MicroApps,
ComplaintManagement
},
directives: {longpress},
directives: {longpress, TransferDom},
data() {
return {
loadIng: 0,
@ -1144,13 +1150,12 @@ export default {
}
this.operateVisible = false;
this.operateItem = $A.isJson(projectItem) ? projectItem : {};
this.$nextTick(() => {
requestAnimationFrame(() => {
const rect = element.getBoundingClientRect();
const parentRect = this.$refs.boxMenu?.getBoundingClientRect() || {top: 0, left: 0}
this.operateStyles = {
left: `${event.clientX - parentRect.left}px`,
top: `${rect.top + this.windowScrollY - parentRect.top}px`,
height: rect.height + 'px',
left: `${event.clientX}px`,
top: `${rect.top}px`,
height: `${rect.height}px`,
}
this.operateVisible = true;
})

View File

@ -292,7 +292,12 @@
</div>
<!--长按右键-->
<div class="operate-position" :style="operateStyles" v-show="operateVisible">
<div
class="operate-position"
v-transfer-dom
:data-transfer="true"
:style="operateStyles"
v-show="operateVisible">
<Dropdown
ref="operate"
trigger="custom"
@ -655,6 +660,7 @@ import DialogGroupVote from "./DialogGroupVote";
import DialogComplaint from "./DialogComplaint";
import touchclick from "../../../directives/touchclick";
import longpress from "../../../directives/longpress";
import TransferDom from "../../../directives/transfer-dom";
import {languageList} from "../../../language";
import {isLocalResourcePath} from "../../../components/Replace/utils";
import emitter from "../../../store/events";
@ -680,7 +686,7 @@ export default {
DialogGroupVote,
DialogComplaint,
},
directives: {touchclick, longpress},
directives: {touchclick, longpress, TransferDom},
props: {
dialogId: {
@ -3080,7 +3086,7 @@ export default {
})
}
}
this.$nextTick(() => {
requestAnimationFrame(() => {
this.operateItem.clientX = event.clientX
this.operateItem.clientY = event.clientY
this.onSelectionchange()
@ -3146,34 +3152,36 @@ export default {
return
}
//
const rect = el.getBoundingClientRect();
const scrollerRect = this.$refs.scroller.$el.getBoundingClientRect();
let top = rect.top + this.windowScrollY,
height = rect.height;
const rect = el.getBoundingClientRect(),
scrollerRect = this.$refs.scroller.$el.getBoundingClientRect();
const operatePosition = {
left: this.operateItem.clientX,
top: rect.top,
height: rect.height
}
if (rect.top < scrollerRect.top) {
top = scrollerRect.top
height -= scrollerRect.top - rect.top
operatePosition.top = scrollerRect.top
operatePosition.height -= scrollerRect.top - rect.top
}
if (rect.bottom > scrollerRect.bottom) {
height -= rect.bottom - scrollerRect.bottom
operatePosition.height -= rect.bottom - scrollerRect.bottom
}
let left = this.operateItem.clientX
if (this.windowWidth < 500) {
if (this.operateItem.created_at) {
left = this.windowWidth / 2
operatePosition.left = this.windowWidth / 2
} else {
left = rect.left + (rect.width / 2)
operatePosition.left = rect.left + (rect.width / 2)
}
}
this.operateStyles = {
left: `${left}px`,
top: `${top}px`,
height: `${height}px`,
left: `${operatePosition.left}px`,
top: `${operatePosition.top}px`,
height: `${operatePosition.height}px`,
}
if (this.location === 'messenger') {
this.operateStyles.marginTop = "calc(var(--status-bar-height) * -1)"
}
this.operateClient = {x: left, y: this.operateItem.clientY};
this.operateClient = {
x: operatePosition.left,
y: this.operateItem.clientY
};
if (this.operateVisible) {
try {
this.$refs.operate.$refs.drop.popper.update()

View File

@ -56,7 +56,12 @@
</div>
</li>
</ul>
<div class="operate-position" :style="operateStyles" v-show="operateVisible">
<div
v-transfer-dom
:data-transfer="true"
class="operate-position"
:style="operateStyles"
v-show="operateVisible">
<Dropdown
trigger="custom"
:placement="windowLandscape ? 'bottom' : 'top'"
@ -77,10 +82,11 @@
<script>
import {mapState} from "vuex";
import longpress from "../../../directives/longpress";
import TransferDom from "../../../directives/transfer-dom";
export default {
name: "ProjectList",
directives: {longpress},
directives: {longpress, TransferDom},
data() {
return {
projectKeyValue: '',
@ -189,13 +195,12 @@ export default {
}
this.operateVisible = false;
this.operateItem = $A.isJson(projectItem) ? projectItem : {};
this.$nextTick(() => {
requestAnimationFrame(() => {
const rect = element.getBoundingClientRect();
const parentRect = this.$el.getBoundingClientRect() || {top: 0, left: 0}
this.operateStyles = {
left: `${event.clientX - parentRect.left}px`,
top: `${rect.top + this.windowScrollY - parentRect.top}px`,
height: rect.height + 'px',
left: `${event.clientX}px`,
top: `${rect.top}px`,
height: `${rect.height}px`,
}
this.operateVisible = true;
})

View File

@ -177,7 +177,12 @@
<Icon @click="tabActive='contacts'" :class="{active:tabActive==='contacts'}" type="md-person" />
</div>
</div>
<div class="operate-position" :style="operateStyles" v-show="operateVisible">
<div
v-transfer-dom
:data-transfer="true"
class="operate-position"
:style="operateStyles"
v-show="operateVisible">
<Dropdown
trigger="custom"
transferClassName="scrollbar-hidden"
@ -272,6 +277,7 @@
import {mapGetters, mapState} from "vuex";
import DialogWrapper from "./components/DialogWrapper";
import longpress from "../../directives/longpress";
import TransferDom from "../../directives/transfer-dom";
import emitter from "../../store/events";
const navDatas = {
@ -290,7 +296,7 @@ const navDatas = {
export default {
components: {DialogWrapper},
directives: {longpress},
directives: {longpress, TransferDom},
data() {
return {
firstLoad: true,
@ -1058,13 +1064,12 @@ export default {
if (!this.operateItem) {
return
}
const rect = element.getBoundingClientRect();
this.$nextTick(() => {
const parentRect = this.$refs.select?.getBoundingClientRect() || {top: 0, left: 0}
requestAnimationFrame(() => {
const rect = element.getBoundingClientRect();
this.operateStyles = {
left: `${event.clientX}px`,
top: `${rect.top + this.windowScrollY - parentRect.top}px`,
height: rect.height + 'px',
top: `${rect.top}px`,
height: `${rect.height}px`,
}
this.operateVisible = true;
})

View File

@ -999,3 +999,16 @@ body.window-portrait {
margin-left: 54px;
}
}
/*操作位置*/
.operate-position {
position: absolute;
top: 0;
left: 0;
width: 1px;
height: auto;
margin-top: var(--window-scroll-y);
opacity: 0;
visibility: hidden;
pointer-events: none;
}

View File

@ -2073,16 +2073,6 @@
}
}
.operate-position {
position: fixed;
top: 0;
left: 0;
width: 1px;
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.apply-reasoning {
margin: 0 0 12px 0;
padding: 0 0 0 13px;

View File

@ -191,14 +191,4 @@
}
}
}
.operate-position {
position: fixed;
top: 0;
left: 0;
width: 1px;
opacity: 0;
visibility: hidden;
pointer-events: none;
}
}

View File

@ -200,15 +200,6 @@
}
}
}
.operate-position {
position: fixed;
top: 0;
left: 0;
width: 1px;
opacity: 0;
visibility: hidden;
pointer-events: none;
}
.manage-project-search {
width: 80%;
padding: 0 6px;

View File

@ -555,15 +555,6 @@
}
}
}
.operate-position {
position: fixed;
top: 0;
left: 0;
width: 1px;
opacity: 0;
visibility: hidden;
pointer-events: none;
}
}
.messenger-msg {
flex: 1;