perf: 优化移动端选择交互

This commit is contained in:
kuaifan 2025-03-26 11:30:46 +08:00
parent 562697da27
commit f652f35c3a
23 changed files with 65 additions and 130 deletions

View File

@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-user-select: none;
user-select: none;
}
@ -65,6 +66,7 @@ body {
box-shadow: none;
-webkit-tap-highlight-color: transparent;
-webkit-user-select: text;
user-select: text;
}
.map-box {

View File

@ -79,9 +79,7 @@
margin: 0;
transition: 0.1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 8px 12px;
font-size: 14px;
border-radius: 4px;

View File

@ -2,7 +2,7 @@
<div class="teditor-wrapper">
<div class="teditor-box" :class="[!inline && spinShow ? 'teditor-loadstyle' : 'teditor-loadedstyle']">
<template v-if="inline">
<div ref="myTextarea" :id="id" v-html="spinShow ? '' : content"></div>
<div ref="myTextarea" class="user-select-auto" :id="id" v-html="spinShow ? '' : content"></div>
<Icon v-if="spinShow" type="ios-loading" :size="18" class="icon-loading icon-inline"></Icon>
</template>
<template v-else>

View File

@ -36,7 +36,7 @@
<!-- 输入框 -->
<div
ref="editor"
class="no-dark-content"
class="no-dark-content user-select-auto"
@click.stop="onClickEditor"
@paste="handlePaste"></div>

View File

@ -11,7 +11,7 @@
@click="handleClick"
v-longpress="{callback: handleLongpress, delay: 300}">
<!--回复-->
<div v-if="!hideReply && msgData.reply_id && showReplyData(msgData.msg.reply_data)" class="dialog-reply no-dark-content" @click="viewReply">
<div v-if="!hideReply && msgData.reply_id && showReplyData(msgData.msg.reply_data)" class="dialog-reply no-dark-content" :class="replyClass" @click="viewReply">
<div class="reply-avatar">
<UserAvatar :userid="msgData.msg.reply_data.userid" :show-icon="false" :show-name="true"/>
</div>
@ -297,24 +297,6 @@ export default {
return this.isLoad(`msg-${this.msgData.id}`)
},
viewClass() {
const {msgData, operateAction, operateEnter, pointerMouse} = this;
const array = [];
if (msgData.type) {
array.push(msgData.type)
}
if (operateAction) {
array.push('operate-action')
if (operateEnter) {
array.push('pointer-mouse')
}
}
if (pointerMouse && array.indexOf('pointer-mouse') === -1) {
array.push('pointer-mouse')
}
return array
},
readList({userId}) {
return this.percentageList.filter(({userid, read_at}) => userid != userId && read_at)
},
@ -331,26 +313,50 @@ export default {
return this.todoList.filter(({done_at}) => !done_at)
},
viewClass() {
const {msgData} = this;
const classArray = [];
if (msgData.type) {
classArray.push(msgData.type)
}
return classArray
},
headClass() {
const {id, reply_id, type, msg, emoji, dot} = this.msgData;
const array = [];
const {msgData, operateAction} = this;
const {id, reply_id, type, msg, emoji, dot} = msgData;
const classArray = [];
if (operateAction) {
classArray.push('operating')
}
if (dot && !this.dotClicks.includes(id)) {
array.push('dot')
classArray.push('dot')
}
if (reply_id === 0 && $A.arrayLength(emoji) === 0) {
if (type === 'text') {
if (/^<img\s+class="emoticon"[^>]*?>$/.test(msg.text)
|| /^\s*<p>\s*([\uD800-\uDBFF][\uDC00-\uDFFF]){1,3}\s*<\/p>\s*$/.test(msg.text)) {
array.push('transparent')
classArray.push('transparent')
}
}
}
return array;
return classArray;
},
replyClass() {
const classArray = [];
if (this.operateEnter || this.pointerMouse) {
classArray.push('user-select-auto')
}
return classArray;
},
contentClass() {
const {type, msg} = this.msgData;
const classArray = [];
if (this.operateEnter || this.pointerMouse) {
classArray.push('user-select-auto')
}
if (type === 'text') {
if (/^<img\s+class="emoticon"[^>]*?>$/.test(msg.text)) {
classArray.push('an-emoticon')

View File

@ -23,7 +23,7 @@
</div>
<span slot="reference">[{{$L('未保存')}}*]</span>
</EPopover>
{{fileName}}
<span class="user-select-auto">{{fileName}}</span>
</div>
<div class="header-user">
<ul>
@ -75,7 +75,7 @@
<Button v-else :disabled="equalContent" :loading="loadSave > 0" class="header-button" size="small" type="primary" @click="handleClick('save')">{{$L('保存')}}</Button>
</template>
</div>
<div class="content-body">
<div class="content-body user-select-auto">
<div v-if="historyShow" class="content-mask"></div>
<template v-if="file.type=='document'">
<template v-if="contentDetail.type=='md'">

View File

@ -4,7 +4,7 @@
<template v-else-if="contentDetail">
<div v-show="headerShow && !['word', 'excel', 'ppt'].includes(file.type)" class="edit-header">
<div class="header-title">
<div class="title-name">{{$A.getFileName(file)}}</div>
<div class="title-name user-select-auto">{{$A.getFileName(file)}}</div>
<Tag color="default">{{$L('只读')}}</Tag>
<div class="refresh">
<Loading v-if="contentLoad"/>
@ -12,7 +12,7 @@
</div>
</div>
</div>
<div class="content-body">
<div class="content-body user-select-auto">
<template v-if="file.type=='document'">
<VMPreview v-if="contentDetail.type=='md'" :value="contentDetail.content"/>
<TEditor v-else :value="contentDetail.content" height="100%" readOnly/>

View File

@ -6,7 +6,7 @@
<div class="project-back" @click="onBack">
<i class="taskfont">&#xe676;</i>
</div>
<h1 @click="showName">{{projectData.name}}</h1>
<h1 @click="showName" class="user-select-auto">{{projectData.name}}</h1>
<div v-if="loading" class="project-load"><Loading/></div>
</div>
<ul class="project-icons">
@ -76,7 +76,7 @@
</ul>
</div>
<div class="project-subbox">
<div class="project-subtitle" @click="showDesc">
<div class="project-subtitle user-select-auto" @click="showDesc">
<VMPreviewNostyle ref="descPreview" :value="projectData.desc"/>
</div>
<div class="project-switch">

View File

@ -1,6 +1,6 @@
<template>
<div class="report-detail">
<div class="report-title">
<div class="report-title user-select-auto">
{{ data.title }}
<Icon v-if="loadIng > 0" type="ios-loading" class="icon-loading"></Icon>
</div>
@ -40,7 +40,7 @@
</div>
</li>
</ul>
<div class="report-content" v-html="data.content"></div>
<div class="report-content user-select-auto" v-html="data.content"></div>
</div>
</div>
</template>

View File

@ -74,7 +74,7 @@
<div v-if="taskDetail.archived_at" class="flow">
<span class="archived" @click.stop="openMenu($event, taskDetail)">{{$L('已归档')}}</span>
</div>
<div class="nav">
<div class="nav user-select-auto">
<p v-if="projectName"><span>{{projectName}}</span></p>
<p v-if="columnName"><span>{{columnName}}</span></p>
<p v-if="taskDetail.id"><span>{{taskDetail.id}}</span></p>

View File

@ -5,14 +5,14 @@
<div v-else-if="info" class="file-preview">
<div v-if="showHeader" class="edit-header">
<div class="header-title">
<div class="title-name">{{pageName}}</div>
<div class="title-name user-select-auto">{{pageName}}</div>
<Tag color="default">{{$L('只读')}}</Tag>
<div class="refresh">
<Icon type="ios-refresh" @click="getInfo" />
</div>
</div>
</div>
<div class="content-body">
<div class="content-body user-select-auto">
<TEditor :value="info.content" height="100%" readOnly/>
</div>
</div>

View File

@ -7,7 +7,6 @@
bottom: 0;
right: 0;
z-index: 99;
user-select: none;
.common-network-exception {
position: fixed;
@ -323,14 +322,23 @@
}
body.window-touch {
user-select: none;
a, img {
-webkit-touch-callout: none;
}
.mobile-back {
display: block;
}
input,
textarea,
.ql-editor {
.user-select-auto {
caret-color: $flow-status-end-color;
user-select: auto;
a, img {
-webkit-touch-callout: default;
}
}
}

View File

@ -17,10 +17,6 @@ $--font-path: '../css/fonts';
@import "~element-sea/packages/theme-chalk/src/dropdown-item";
@import "~element-sea/packages/theme-chalk/src/notification";
.el-dropdown-menu {
user-select: none;
}
.el-dropdown-menu__item {
min-width: 100px;
.item {

View File

@ -102,7 +102,6 @@ body {
}
.ivu-select-dropdown {
user-select: none;
max-height: 360px;
&.select-node {

View File

@ -245,7 +245,7 @@
color: #0bc037;
background-color: transparent;
margin-right: 0;
-webkit-user-select: auto;
user-select: auto;
> span {
margin: 0 2px;
}
@ -298,7 +298,6 @@
display: flex;
align-items: center;
justify-content: flex-end;
user-select: none;
> li {
width: 30px;
height: 30px;
@ -589,7 +588,6 @@
text-align: center;
display: inline-block;
cursor: pointer;
user-select: none;
> img {
max-width: 100%;
max-height: 100%;
@ -1003,7 +1001,6 @@
display: flex;
align-items: center;
justify-content: center;
user-select: none;
margin: 0 -12px;
&.activation {
> li {

View File

@ -672,12 +672,6 @@
max-width: 70%;
}
&.operate-action {
.dialog-head {
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
}
}
.dialog-username {
max-width: 100%;
height: 22px;
@ -699,6 +693,10 @@
background-color: transparent !important;
}
&.operating {
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2);
}
&.dot {
position: relative;
&:after {
@ -1940,7 +1938,6 @@
background-color: #ffffff;
border: 1px solid #eeeeee;
cursor: pointer;
user-select: none;
display: flex;
align-content: center;
justify-content: center;
@ -2435,7 +2432,7 @@ body:not(.window-touch) {
}
}
}
.operate-action-top{
.operate-action-top {
width: auto;
> li {
margin-bottom: 0;
@ -2493,7 +2490,6 @@ body:not(.window-touch) {
body.window-touch {
.dialog-wrapper {
.dialog-scroller {
user-select: none;
.dialog-item {
.dialog-view {
.dialog-head {
@ -2517,13 +2513,6 @@ body.window-touch {
}
}
}
&.pointer-mouse {
.dialog-head {
.dialog-content {
user-select: text;
}
}
}
}
}
}
@ -2666,15 +2655,13 @@ body.window-portrait {
.dialog-item {
.dialog-view {
&.text,
&.file,
&.location,
&.template {
max-width: calc(100% - 80px);
}
.dialog-head {
.dialog-content {
a, img {
-webkit-touch-callout: none;
}
.content-text {
> pre {
font-size: 15px;
@ -2694,15 +2681,6 @@ body.window-portrait {
}
}
}
&.pointer-mouse {
.dialog-head {
.dialog-content {
a, img {
-webkit-touch-callout: default;
}
}
}
}
}
}
}

View File

@ -65,7 +65,6 @@
width: 100%;
overflow: auto;
background-color: #f8f8f8;
user-select: none;
> li {
padding: 16px;
margin: 16px;

View File

@ -79,7 +79,6 @@ body.window-portrait {
}
.calendar-box {
padding: 0 24px 5px;
user-select: none;
.calendar-wrapper {
.tui-full-calendar-section-button {
> button {

View File

@ -368,18 +368,6 @@
opacity: 0;
}
body.window-touch {
.page-messenger {
.messenger-wrapper {
.messenger-select {
.messenger-list {
user-select: none;
}
}
}
}
}
body.window-portrait {
.page-dashboard {
.dashboard-wrapper {
@ -413,7 +401,6 @@ body.window-portrait {
}
.dashboard-ul {
margin-bottom: 20px;
user-select: none;
&.ul-hidden {
margin-bottom: 0;
}

View File

@ -737,7 +737,6 @@ body.window-portrait {
}
.file-drag {
.file-list {
user-select: none;
> ul {
grid-template-columns: repeat(auto-fill, 80px);
grid-gap: 4px;
@ -778,15 +777,3 @@ body.window-portrait {
}
}
}
body.window-touch {
.page-file {
.file-wrapper {
.file-drag {
.file-list {
user-select: none;
}
}
}
}
}

View File

@ -438,14 +438,6 @@
}
}
body.window-touch {
.page-manage {
.manage-box-menu {
user-select: none;
}
}
}
body.window-portrait {
.page-manage {
&.show-tabbar {

View File

@ -241,7 +241,6 @@
padding: 0;
height: auto;
width: auto;
user-select: none;
}
.bot {
color: $primary-color;
@ -658,18 +657,6 @@
}
}
body.window-touch {
.page-messenger {
.messenger-wrapper {
.messenger-select {
.messenger-list {
user-select: none;
}
}
}
}
}
body.window-portrait {
.page-messenger {
.messenger-wrapper {
@ -710,7 +697,6 @@ body.window-portrait {
.messenger-list {
ul {
&.dialog {
user-select: none;
> li {
.user-avatar {
.common-avatar {
@ -736,7 +722,6 @@ body.window-portrait {
}
}
&.contacts {
user-select: none;
> li {
&.loaded {
height: 58px;

View File

@ -2,6 +2,7 @@
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-user-select: none;
user-select: none;
}
@ -65,6 +66,7 @@ body {
box-shadow: none;
-webkit-tap-highlight-color: transparent;
-webkit-user-select: text;
user-select: text;
}
.map-box {