mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-20 07:58:12 +00:00
整理右键、长按
This commit is contained in:
parent
e15f7f6377
commit
a2dcd69efd
@ -156,8 +156,8 @@
|
|||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
<div class="menu-title">{{$L('文件')}}</div>
|
<div class="menu-title">{{$L('文件')}}</div>
|
||||||
</li>
|
</li>
|
||||||
<li class="menu-project">
|
<li ref="menuProject" class="menu-project">
|
||||||
<ul ref="projectWrapper" :class="listClassName" @scroll="operateVisible = false">
|
<ul :class="listClassName" @scroll="operateVisible = false">
|
||||||
<li
|
<li
|
||||||
v-for="(item, key) in projectLists"
|
v-for="(item, key) in projectLists"
|
||||||
:ref="`project_${item.id}`"
|
:ref="`project_${item.id}`"
|
||||||
@ -192,6 +192,7 @@
|
|||||||
<div class="operate-position" :style="operateStyles">
|
<div class="operate-position" :style="operateStyles">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
trigger="custom"
|
trigger="custom"
|
||||||
|
:placement="$isDesktop ? 'bottom' : 'top'"
|
||||||
:visible="operateVisible"
|
:visible="operateVisible"
|
||||||
@on-clickoutside="operateVisible = false"
|
@on-clickoutside="operateVisible = false"
|
||||||
transfer>
|
transfer>
|
||||||
@ -1008,7 +1009,7 @@ export default {
|
|||||||
this.operateItem = $A.isJson(projectItem) ? projectItem : {};
|
this.operateItem = $A.isJson(projectItem) ? projectItem : {};
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const projectRect = el.getBoundingClientRect();
|
const projectRect = el.getBoundingClientRect();
|
||||||
const wrapRect = this.$refs.projectWrapper.getBoundingClientRect();
|
const wrapRect = this.$refs.menuProject.getBoundingClientRect();
|
||||||
this.operateStyles = {
|
this.operateStyles = {
|
||||||
left: `${event.clientX - wrapRect.left}px`,
|
left: `${event.clientX - wrapRect.left}px`,
|
||||||
top: `${projectRect.top}px`,
|
top: `${projectRect.top}px`,
|
||||||
@ -1027,7 +1028,7 @@ export default {
|
|||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.$store.dispatch("saveProject", data);
|
this.$store.dispatch("saveProject", data);
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const active = this.$refs.projectWrapper.querySelector(".active")
|
const active = this.$refs.menuProject.querySelector(".active")
|
||||||
if (active) {
|
if (active) {
|
||||||
$A.scrollToView(active, {
|
$A.scrollToView(active, {
|
||||||
behavior: 'instant',
|
behavior: 'instant',
|
||||||
|
|||||||
@ -7,7 +7,10 @@
|
|||||||
|
|
||||||
<div class="dialog-head">
|
<div class="dialog-head">
|
||||||
<!--详情-->
|
<!--详情-->
|
||||||
<div class="dialog-content" :class="contentClass">
|
<div
|
||||||
|
class="dialog-content"
|
||||||
|
:class="contentClass"
|
||||||
|
v-longpress="handleLongpress">
|
||||||
<!--文本-->
|
<!--文本-->
|
||||||
<div v-if="msgData.type === 'text'" class="content-text no-dark-content">
|
<div v-if="msgData.type === 'text'" class="content-text no-dark-content">
|
||||||
<pre @click="viewText" v-html="textMsg(msgData.msg.text)"></pre>
|
<pre @click="viewText" v-html="textMsg(msgData.msg.text)"></pre>
|
||||||
@ -60,17 +63,6 @@
|
|||||||
<!--未知-->
|
<!--未知-->
|
||||||
<div v-else class="content-unknown">{{$L("未知的消息类型")}}</div>
|
<div v-else class="content-unknown">{{$L("未知的消息类型")}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--菜单-->
|
|
||||||
<div v-if="showMenu" class="dialog-menu">
|
|
||||||
<div class="menu-icon">
|
|
||||||
<Icon v-if="msgData.userid == userId" @click="withdraw" type="md-undo" :title="$L('撤回')"/>
|
|
||||||
<template v-if="msgData.type === 'file'">
|
|
||||||
<Icon @click="viewFile" type="md-eye" :title="$L('查看')"/>
|
|
||||||
<Icon @click="downFile" type="md-arrow-round-down" :title="$L('下载')"/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--时间/阅读-->
|
<!--时间/阅读-->
|
||||||
@ -117,10 +109,12 @@
|
|||||||
import WCircle from "../../../components/WCircle";
|
import WCircle from "../../../components/WCircle";
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
import {Store} from "le5le-store";
|
import {Store} from "le5le-store";
|
||||||
|
import longpress from "../../../directives/longpress";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "DialogView",
|
name: "DialogView",
|
||||||
components: {WCircle},
|
components: {WCircle},
|
||||||
|
directives: {longpress},
|
||||||
props: {
|
props: {
|
||||||
msgData: {
|
msgData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -167,10 +161,6 @@ export default {
|
|||||||
return this.allList.filter(({read_at}) => !read_at)
|
return this.allList.filter(({read_at}) => !read_at)
|
||||||
},
|
},
|
||||||
|
|
||||||
showMenu() {
|
|
||||||
return this.msgData.userid == this.userId || this.msgData.type === 'file'
|
|
||||||
},
|
|
||||||
|
|
||||||
contentClass() {
|
contentClass() {
|
||||||
const {type, msg} = this.msgData;
|
const {type, msg} = this.msgData;
|
||||||
const classArray = [];
|
const classArray = [];
|
||||||
@ -203,6 +193,14 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
handleLongpress(event, el) {
|
||||||
|
this.$emit("on-longpress", {
|
||||||
|
event,
|
||||||
|
el,
|
||||||
|
msgData: this.msgData
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
msgRead() {
|
msgRead() {
|
||||||
if (this.msgData._r === true) {
|
if (this.msgData._r === true) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -94,7 +94,12 @@
|
|||||||
<div class="dialog-avatar">
|
<div class="dialog-avatar">
|
||||||
<UserAvatar :userid="item.userid" :tooltipDisabled="item.userid == userId" :size="30"/>
|
<UserAvatar :userid="item.userid" :tooltipDisabled="item.userid == userId" :size="30"/>
|
||||||
</div>
|
</div>
|
||||||
<DialogView :msg-data="item" :dialog-type="dialogData.type" :hide-percentage="isMyDialog"/>
|
<DialogView
|
||||||
|
:ref="`msg_${item.id}`"
|
||||||
|
:msg-data="item"
|
||||||
|
:dialog-type="dialogData.type"
|
||||||
|
:hide-percentage="isMyDialog"
|
||||||
|
@on-longpress="onLongpress"/>
|
||||||
</DynamicScrollerItem>
|
</DynamicScrollerItem>
|
||||||
</template>
|
</template>
|
||||||
</DynamicScroller>
|
</DynamicScroller>
|
||||||
@ -125,6 +130,25 @@
|
|||||||
<div v-if="dialogDrag" class="drag-over" @click="dialogDrag=false">
|
<div v-if="dialogDrag" class="drag-over" @click="dialogDrag=false">
|
||||||
<div class="drag-text">{{$L('拖动到这里发送')}}</div>
|
<div class="drag-text">{{$L('拖动到这里发送')}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="operate-position" :style="operateStyles">
|
||||||
|
<Dropdown
|
||||||
|
trigger="custom"
|
||||||
|
:placement="$isDesktop ? 'bottom' : 'top'"
|
||||||
|
:visible="operateVisible"
|
||||||
|
@on-clickoutside="operateVisible = false"
|
||||||
|
@on-click="onOperate"
|
||||||
|
transfer>
|
||||||
|
<div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div>
|
||||||
|
<DropdownMenu slot="list">
|
||||||
|
<DropdownItem name="forward">{{ $L('转发') }}</DropdownItem>
|
||||||
|
<DropdownItem v-if="operateItem.userid == userId" name="withdraw">{{ $L('撤回') }}</DropdownItem>
|
||||||
|
<template v-if="operateItem.type === 'file'">
|
||||||
|
<DropdownItem name="view" divided>{{ $L('查看文件') }}</DropdownItem>
|
||||||
|
<DropdownItem name="down">{{ $L('下载文件') }}</DropdownItem>
|
||||||
|
</template>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!--拖动发送提示-->
|
<!--拖动发送提示-->
|
||||||
<Modal
|
<Modal
|
||||||
@ -232,6 +256,10 @@ export default {
|
|||||||
groupInfoShow: false,
|
groupInfoShow: false,
|
||||||
|
|
||||||
wrapperStyle: {},
|
wrapperStyle: {},
|
||||||
|
|
||||||
|
operateStyles: {},
|
||||||
|
operateVisible: false,
|
||||||
|
operateItem: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -704,6 +732,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onScroll() {
|
onScroll() {
|
||||||
|
this.operateVisible = false;
|
||||||
this.__onScroll && clearTimeout(this.__onScroll);
|
this.__onScroll && clearTimeout(this.__onScroll);
|
||||||
this.__onScroll = setTimeout(_ => {
|
this.__onScroll = setTimeout(_ => {
|
||||||
const {scrollE} = this.scrollInfo();
|
const {scrollE} = this.scrollInfo();
|
||||||
@ -722,6 +751,41 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onLongpress({event, el, msgData}) {
|
||||||
|
this.operateVisible = false;
|
||||||
|
this.operateItem = $A.isJson(msgData) ? msgData : {};
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const projectRect = el.getBoundingClientRect();
|
||||||
|
const wrapRect = this.$el.getBoundingClientRect();
|
||||||
|
this.operateStyles = {
|
||||||
|
left: `${event.clientX - wrapRect.left}px`,
|
||||||
|
top: `${projectRect.top}px`,
|
||||||
|
height: projectRect.height + 'px',
|
||||||
|
}
|
||||||
|
this.operateVisible = true;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
onOperate(name) {
|
||||||
|
switch (name) {
|
||||||
|
case "forward":
|
||||||
|
// todo 转发功能
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "withdraw":
|
||||||
|
this.$refs[`msg_${this.operateItem.id}`].withdraw()
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "view":
|
||||||
|
this.$refs[`msg_${this.operateItem.id}`].viewFile()
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "down":
|
||||||
|
this.$refs[`msg_${this.operateItem.id}`].downFile()
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
backListener(e) {
|
backListener(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
},
|
},
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
</Input>
|
</Input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul ref="projectWrapper" @scroll="operateVisible = false">
|
<ul @scroll="operateVisible = false">
|
||||||
<template v-if="projectLists.length === 0">
|
<template v-if="projectLists.length === 0">
|
||||||
<li v-if="projectKeyLoading > 0" class="loading"><Loading/></li>
|
<li v-if="projectKeyLoading > 0" class="loading"><Loading/></li>
|
||||||
<li v-else class="nothing">
|
<li v-else class="nothing">
|
||||||
@ -55,7 +55,7 @@
|
|||||||
<div class="operate-position" :style="operateStyles">
|
<div class="operate-position" :style="operateStyles">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
trigger="custom"
|
trigger="custom"
|
||||||
placement="top"
|
:placement="$isDesktop ? 'bottom' : 'top'"
|
||||||
:visible="operateVisible"
|
:visible="operateVisible"
|
||||||
@on-clickoutside="operateVisible = false"
|
@on-clickoutside="operateVisible = false"
|
||||||
transfer>
|
transfer>
|
||||||
@ -181,7 +181,7 @@ export default {
|
|||||||
this.operateItem = $A.isJson(projectItem) ? projectItem : {};
|
this.operateItem = $A.isJson(projectItem) ? projectItem : {};
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const projectRect = el.getBoundingClientRect();
|
const projectRect = el.getBoundingClientRect();
|
||||||
const wrapRect = this.$refs.projectWrapper.getBoundingClientRect();
|
const wrapRect = this.$el.getBoundingClientRect();
|
||||||
this.operateStyles = {
|
this.operateStyles = {
|
||||||
left: `${event.clientX - wrapRect.left}px`,
|
left: `${event.clientX - wrapRect.left}px`,
|
||||||
top: `${projectRect.top}px`,
|
top: `${projectRect.top}px`,
|
||||||
|
|||||||
@ -32,7 +32,6 @@
|
|||||||
static>
|
static>
|
||||||
<ul
|
<ul
|
||||||
v-if="tabActive==='dialog'"
|
v-if="tabActive==='dialog'"
|
||||||
ref="dialogWrapper"
|
|
||||||
class="dialog">
|
class="dialog">
|
||||||
<li v-if="dialogList.length === 0" class="nothing">
|
<li v-if="dialogList.length === 0" class="nothing">
|
||||||
{{$L(dialogKey ? `没有任何与"${dialogKey}"相关的会话` : `没有任何会话`)}}
|
{{$L(dialogKey ? `没有任何与"${dialogKey}"相关的会话` : `没有任何会话`)}}
|
||||||
@ -103,10 +102,10 @@
|
|||||||
<div class="operate-position" :style="operateStyles">
|
<div class="operate-position" :style="operateStyles">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
trigger="custom"
|
trigger="custom"
|
||||||
:transfer="true"
|
|
||||||
:placement="$isDesktop ? 'bottom' : 'top'"
|
:placement="$isDesktop ? 'bottom' : 'top'"
|
||||||
:visible="operateVisible"
|
:visible="operateVisible"
|
||||||
@on-clickoutside="operateVisible = false">
|
@on-clickoutside="operateVisible = false"
|
||||||
|
transfer>
|
||||||
<div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div>
|
<div :style="{userSelect:operateVisible ? 'none' : 'auto', height: operateStyles.height}"></div>
|
||||||
<DropdownMenu slot="list">
|
<DropdownMenu slot="list">
|
||||||
<DropdownItem @click.native="handleTopClick">
|
<DropdownItem @click.native="handleTopClick">
|
||||||
@ -551,7 +550,7 @@ export default {
|
|||||||
this.operateItem = $A.isJson(dialogItem) ? dialogItem : {};
|
this.operateItem = $A.isJson(dialogItem) ? dialogItem : {};
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const dialogRect = el.getBoundingClientRect();
|
const dialogRect = el.getBoundingClientRect();
|
||||||
const wrapRect = this.$refs.dialogWrapper.getBoundingClientRect();
|
const wrapRect = this.$refs.list.$el.getBoundingClientRect();
|
||||||
this.operateStyles = {
|
this.operateStyles = {
|
||||||
left: `${event.clientX - wrapRect.left}px`,
|
left: `${event.clientX - wrapRect.left}px`,
|
||||||
top: `${dialogRect.top}px`,
|
top: `${dialogRect.top}px`,
|
||||||
|
|||||||
@ -219,14 +219,6 @@
|
|||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.dialog-head {
|
|
||||||
.dialog-menu {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-username {
|
.dialog-username {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
@ -557,37 +549,6 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-menu {
|
|
||||||
opacity: 0;
|
|
||||||
margin-left: 6px;
|
|
||||||
transition: all 0.3s;
|
|
||||||
|
|
||||||
.menu-icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background-color: #ffffff;
|
|
||||||
|
|
||||||
> i {
|
|
||||||
flex: 1;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 4px 6px;
|
|
||||||
color: #999;
|
|
||||||
font-size: 13px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
& + i {
|
|
||||||
border-left: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-foot {
|
.dialog-foot {
|
||||||
@ -768,11 +729,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-menu {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-foot {
|
.dialog-foot {
|
||||||
@ -873,6 +829,16 @@
|
|||||||
color: $primary-text-color;
|
color: $primary-text-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.operate-position {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 1px;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-wrapper-read-poptip {
|
.dialog-wrapper-read-poptip {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user