mirror of
https://github.com/kuaifan/dootask.git
synced 2026-03-19 04:03:38 +00:00
perf: 对话顶部提示
This commit is contained in:
parent
66f0bef271
commit
42e54d8a6e
@ -1033,8 +1033,9 @@ class DialogController extends AbstractController
|
|||||||
*
|
*
|
||||||
* @apiParam {Number} dialog_id 会话ID
|
* @apiParam {Number} dialog_id 会话ID
|
||||||
* @apiParam {String} type 类型
|
* @apiParam {String} type 类型
|
||||||
* - read
|
* - read: 已读
|
||||||
* - unread
|
* - unread: 未读
|
||||||
|
* @apiParam {Number} [after_msg_id] 仅标记已读指定之后(含)的消息
|
||||||
*
|
*
|
||||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||||
@ -1045,6 +1046,7 @@ class DialogController extends AbstractController
|
|||||||
$user = User::auth();
|
$user = User::auth();
|
||||||
$dialogId = intval(Request::input('dialog_id'));
|
$dialogId = intval(Request::input('dialog_id'));
|
||||||
$type = Request::input('type');
|
$type = Request::input('type');
|
||||||
|
$afterMsgId = intval(Request::input('after_msg_id'));
|
||||||
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
$dialogUser = WebSocketDialogUser::whereUserid($user->userid)->whereDialogId($dialogId)->first();
|
||||||
if (!$dialogUser) {
|
if (!$dialogUser) {
|
||||||
return Base::retError("会话不存在");
|
return Base::retError("会话不存在");
|
||||||
@ -1054,27 +1056,31 @@ class DialogController extends AbstractController
|
|||||||
];
|
];
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'read':
|
case 'read':
|
||||||
|
$data['mark_unread'] = 0;
|
||||||
$data['unread'] = 0;
|
$data['unread'] = 0;
|
||||||
$data['first_umid'] = 0;
|
$data['mention'] = 0;
|
||||||
WebSocketDialogMsgRead::whereUserid($user->userid)
|
$builder = WebSocketDialogMsgRead::whereUserid($user->userid)->whereReadAt(null)->whereDialogId($dialogId);
|
||||||
->whereReadAt(null)
|
if ($afterMsgId > 0) {
|
||||||
->whereDialogId($dialogId)
|
$unBuilder = $builder->clone()->where('msg_id', '<', $afterMsgId);
|
||||||
->chunkById(100, function ($list) {
|
$data['unread'] = $unBuilder->count();
|
||||||
WebSocketDialogMsgRead::onlyMarkRead($list);
|
$data['mention'] = $data['unread'] > 0 ? $unBuilder->whereMention(1)->count() : 0;
|
||||||
});
|
$builder->where('msg_id', '>=', $afterMsgId);
|
||||||
$dialogUser->mark_unread = 0;
|
}
|
||||||
$dialogUser->save();
|
$builder->chunkById(100, function ($list) {
|
||||||
|
WebSocketDialogMsgRead::onlyMarkRead($list);
|
||||||
|
});
|
||||||
|
$data['position_msgs'] = WebSocketDialog::find($dialogId)?->getPositionMsgs($user->userid) ?: [];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'unread':
|
case 'unread':
|
||||||
$dialogUser->mark_unread = 1;
|
$data['mark_unread'] = 1;
|
||||||
$dialogUser->save();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return Base::retError("参数错误");
|
return Base::retError("参数错误");
|
||||||
}
|
}
|
||||||
$data['mark_unread'] = $dialogUser->mark_unread;
|
$dialogUser->mark_unread = $data['mark_unread'];
|
||||||
|
$dialogUser->save();
|
||||||
return Base::retSuccess("success", $data);
|
return Base::retSuccess("success", $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,16 +76,16 @@ class WebSocketDialog extends AbstractModel
|
|||||||
// 最后消息
|
// 最后消息
|
||||||
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first();
|
$this->last_msg = WebSocketDialogMsg::whereDialogId($this->id)->orderByDesc('id')->first();
|
||||||
// 未读信息
|
// 未读信息
|
||||||
$unreadBuilder = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null);
|
$unBuilder = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null);
|
||||||
$this->unread = $unreadBuilder->count();
|
$this->unread = $unBuilder->count();
|
||||||
$this->mention = 0;
|
$this->mention = 0;
|
||||||
$this->last_umid = 0;
|
$this->last_umid = 0;
|
||||||
$this->first_umid = 0; // 第一条未读消息
|
$this->position_msgs = [];
|
||||||
if ($this->unread > 0) {
|
if ($this->unread > 0) {
|
||||||
$this->mention = $unreadBuilder->clone()->whereMention(1)->count();
|
$this->mention = $unBuilder->clone()->whereMention(1)->count();
|
||||||
$this->last_umid = intval($unreadBuilder->clone()->orderByDesc('msg_id')->value('msg_id'));
|
$this->last_umid = intval($unBuilder->clone()->orderByDesc('msg_id')->value('msg_id'));
|
||||||
if ($hasData === true) {
|
if ($hasData === true) {
|
||||||
$this->first_umid = intval($unreadBuilder->clone()->orderBy('msg_id')->value('msg_id'));
|
$this->position_msgs = $this->getPositionMsgs($userid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->mark_unread = $this->mark_unread ?? $dialogUserFun('mark_unread');
|
$this->mark_unread = $this->mark_unread ?? $dialogUserFun('mark_unread');
|
||||||
@ -156,6 +156,34 @@ class WebSocketDialog extends AbstractModel
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取定位消息
|
||||||
|
* @param $userid
|
||||||
|
* @return array[]
|
||||||
|
*/
|
||||||
|
public function getPositionMsgs($userid)
|
||||||
|
{
|
||||||
|
$builder = WebSocketDialogMsgRead::whereDialogId($this->id)->whereUserid($userid)->whereReadAt(null);
|
||||||
|
$array = [];
|
||||||
|
// @我的消息
|
||||||
|
$mention_id = intval($builder->clone()->whereMention(1)->orderByDesc('msg_id')->value('msg_id'));
|
||||||
|
if ($mention_id > 0) {
|
||||||
|
$array[] = [
|
||||||
|
'msg_id' => $mention_id,
|
||||||
|
'label' => Base::Lang('@我的消息'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// 最早一条未读消息
|
||||||
|
$first_id = intval($builder->clone()->orderBy('msg_id')->value('msg_id'));
|
||||||
|
if ($first_id > 0) {
|
||||||
|
$array[] = [
|
||||||
|
'msg_id' => $first_id,
|
||||||
|
'label' => 'unread'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入聊天室
|
* 加入聊天室
|
||||||
* @param int|array $userid 加入的会员ID或会员ID组
|
* @param int|array $userid 加入的会员ID或会员ID组
|
||||||
|
|||||||
@ -99,10 +99,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--顶部提示-->
|
<!--顶部提示-->
|
||||||
<div v-if="beforeUnread > 0" class="dialog-top" :class="{'down': tagShow}">
|
<div v-if="positionMsg" class="dialog-position" :class="{'down': tagShow}">
|
||||||
<div class="top-unread" @click="goBeforeUnread">
|
<div class="position-label" @click="onPositionMark">
|
||||||
<Icon v-if="beforeLoad" type="ios-loading" class="icon-loading"></Icon>
|
<Icon v-if="positionLoad > 0" type="ios-loading" class="icon-loading"></Icon>
|
||||||
<span>{{$L(`未读消息${beforeUnread}条`)}}</span>
|
<i v-else class="taskfont"></i>
|
||||||
|
{{positionMsg.label}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -543,7 +544,7 @@ export default {
|
|||||||
scrollAction: 0,
|
scrollAction: 0,
|
||||||
scrollTmp: 0,
|
scrollTmp: 0,
|
||||||
|
|
||||||
beforeLoad: false,
|
positionLoad: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -775,16 +776,24 @@ export default {
|
|||||||
return null
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeUnread() {
|
positionMsg() {
|
||||||
const {unread, first_umid} = this.dialogData
|
const {unread, position_msgs} = this.dialogData
|
||||||
if (unread > 0
|
if (unread === 0 || this.allMsgs.length === 0 ||position_msgs.length === 0) {
|
||||||
&& first_umid > 0
|
return null
|
||||||
&& this.allMsgs.length > 0
|
|
||||||
&& this.allMsgs.findIndex(({id}) => id == first_umid) === -1) {
|
|
||||||
return unread
|
|
||||||
}
|
}
|
||||||
return 0
|
const item = position_msgs.sort((a, b) => {
|
||||||
}
|
return b.msg_id - a.msg_id
|
||||||
|
})[0]
|
||||||
|
if (this.allMsgs.findIndex(({id}) => id == item.msg_id) === -1) {
|
||||||
|
if (item.label === 'unread') {
|
||||||
|
return Object.assign(item, {
|
||||||
|
'label': this.$L(`未读消息${unread}条`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@ -2256,22 +2265,26 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
goBeforeUnread() {
|
onPositionMark() {
|
||||||
if (this.beforeUnread === 0 || this.beforeLoad) {
|
if (this.positionLoad > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
this.beforeLoad = true
|
this.positionLoad++
|
||||||
const {first_umid} = this.dialogData
|
const {msg_id} = this.positionMsg;
|
||||||
this.$store.dispatch("dialogMsgMark", {
|
this.$store.dispatch("dialogMsgMark", {
|
||||||
dialog_id: this.dialogId,
|
dialog_id: this.dialogId,
|
||||||
type: 'read'
|
type: 'read',
|
||||||
|
after_msg_id: msg_id,
|
||||||
}).then(_ => {
|
}).then(_ => {
|
||||||
this.onPositionId(first_umid)
|
this.positionLoad++
|
||||||
|
this.onPositionId(msg_id).finally(_ => {
|
||||||
|
this.positionLoad--
|
||||||
|
})
|
||||||
}).catch(({msg}) => {
|
}).catch(({msg}) => {
|
||||||
$A.modalError(msg)
|
$A.modalError(msg)
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.beforeLoad = false
|
this.positionLoad--
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -1086,26 +1086,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-top {
|
.dialog-position {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 78px;
|
top: 100px;
|
||||||
left: 0;
|
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-end;
|
||||||
.top-unread {
|
.position-label {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 6px 12px;
|
padding: 5px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 18px 0 0 18px;
|
||||||
box-shadow: 0 2px 8px 0 rgba($primary-text-color, 0.33);
|
color: #ffffff;
|
||||||
background: #fff;
|
background-color: $primary-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
> i {
|
> i {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1625,10 +1628,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dialog-top {
|
.dialog-position {
|
||||||
top: 68px;
|
|
||||||
&.down {
|
&.down {
|
||||||
top: 98px;
|
top: 130px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dialog-footer {
|
.dialog-footer {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user