perf: 优化消息标记已读/未读

This commit is contained in:
kuaifan 2022-03-10 14:41:29 +08:00
parent 30c149be31
commit 48b7f4924e
9 changed files with 72 additions and 30 deletions

View File

@ -41,7 +41,7 @@ class DialogController extends AbstractController
{
$user = User::auth();
//
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at'])
$list = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.is_mark_unread'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('u.userid', $user->userid)
->orderByDesc('u.top_at')
@ -74,7 +74,7 @@ class DialogController extends AbstractController
//
$dialog_id = intval(Request::input('dialog_id'));
//
$item = WebSocketDialog::select(['web_socket_dialogs.*'])
$item = WebSocketDialog::select(['web_socket_dialogs.*', 'u.top_at', 'u.is_mark_unread'])
->join('web_socket_dialog_users as u', 'web_socket_dialogs.id', '=', 'u.dialog_id')
->where('web_socket_dialogs.id', $dialog_id)
->where('u.userid', $user->userid)
@ -524,19 +524,41 @@ class DialogController extends AbstractController
if (!$dialogUser) {
return Base::retError("会话不存在");
}
if ($type == 'read') {
WebSocketDialogMsgRead::whereUserid($user->userid)
->whereReadAt(null)
->whereDialogId($dialogId)
->update(
[
'read_at' => Carbon::now()
]);
$dialogUser->is_mark_unread = 0;
$dialogUser->save();
} elseif ($type == 'unread') {
$dialogUser->is_mark_unread = 1;
$dialogUser->save();
switch ($type) {
case 'read':
WebSocketDialogMsgRead::whereUserid($user->userid)
->whereReadAt(null)
->whereDialogId($dialogId)
->chunkById(100, function ($list) {
/** @var WebSocketDialogMsgRead $item */
$dialogMsg = [];
foreach ($list as $item) {
$item->read_at = Carbon::now();
$item->save();
if (isset($dialogMsg[$item->msg_id])) {
$dialogMsg[$item->msg_id]['re']++;
} else {
$dialogMsg[$item->msg_id] = [
'ob' => $item->webSocketDialogMsg,
're' => 1
];
}
}
foreach ($dialogMsg as $item) {
$item['ob']?->generatePercentage($item['re']);
}
});
$dialogUser->is_mark_unread = 0;
$dialogUser->save();
break;
case 'unread':
$dialogUser->is_mark_unread = 1;
$dialogUser->save();
break;
default:
return Base::retError("参数错误");
}
return Base::retSuccess("success");
}

View File

@ -105,9 +105,8 @@ class WebSocketDialog extends AbstractModel
$last_msg = WebSocketDialogMsg::whereDialogId($dialog->id)->orderByDesc('id')->first();
$dialog->last_msg = $last_msg;
// 未读信息
$unread = WebSocketDialogMsgRead::whereDialogId($dialog->id)->whereUserid($userid)->whereReadAt(null)->count();
$isMarkUnread = WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->whereIsMarkUnread(1)->exists();
$dialog->unread = $unread > 0 ? $unread : ($isMarkUnread ? 1 : 0);
$dialog->unread = WebSocketDialogMsgRead::whereDialogId($dialog->id)->whereUserid($userid)->whereReadAt(null)->count();
$dialog->is_mark_unread = $dialog->is_mark_unread ?? WebSocketDialogUser::whereDialogId($dialog->id)->whereUserid($userid)->value('is_mark_unread');
// 对话人数
$builder = WebSocketDialogUser::whereDialogId($dialog->id);
$dialog->people = $builder->count();

View File

@ -96,12 +96,12 @@ class WebSocketDialogMsg extends AbstractModel
/**
* 获取占比
* @param bool $increment 是否新增阅读数
* @param bool|int $increment 是否新增阅读数
* @return int
*/
public function generatePercentage($increment = false) {
if ($increment) {
$this->increment('read');
$this->increment('read', is_bool($increment) ? 1 : $increment);
}
if ($this->read > $this->send || empty($this->send)) {
return $this->appendattrs['percentage'] = 100;

View File

@ -11,6 +11,7 @@ namespace App\Models;
* @property int|null $userid 发送会员ID
* @property int|null $after 在阅读之后才添加的记录
* @property string|null $read_at 阅读时间
* @property-read \App\Models\WebSocketDialogMsg|null $webSocketDialogMsg
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogMsgRead query()
@ -29,4 +30,12 @@ class WebSocketDialogMsgRead extends AbstractModel
parent::__construct($attributes);
$this->timestamps = false;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function webSocketDialogMsg(): \Illuminate\Database\Eloquent\Relations\HasOne
{
return $this->hasOne(WebSocketDialogMsg::class, 'id', 'msg_id');
}
}

View File

@ -376,6 +376,15 @@
} else {
window.open(url)
}
},
/**
* 返回对话未读数量
* @param dialog
* @returns {*|number}
*/
getDialogUnread(dialog) {
return dialog ? (dialog.unread || dialog.is_mark_unread || 0) : 0
}
});

View File

@ -490,7 +490,8 @@ export default {
msgAllUnread() {
let num = 0;
this.cacheDialogs.some(({unread}) => {
this.cacheDialogs.some(dialog => {
let unread = $A.getDialogUnread(dialog);
if (unread) {
num += unread;
}

View File

@ -576,7 +576,7 @@ export default {
msgUnread() {
const {cacheDialogs, projectData} = this;
const dialog = cacheDialogs.find(({id}) => id === projectData.dialog_id);
return dialog ? dialog.unread : 0;
return dialog ? $A.getDialogUnread(dialog) : 0;
},
panelTask() {

View File

@ -58,7 +58,7 @@
</div>
<div class="dialog-text no-dark-mode">{{formatLastMsg(dialog.last_msg)}}</div>
</div>
<Badge class="dialog-num" :count="dialog.unread"/>
<Badge class="dialog-num" :count="$A.getDialogUnread(dialog)"/>
</li>
</ul>
<ul v-else class="contacts">
@ -85,7 +85,7 @@
<DropdownItem @click.native="handleTopClick">
{{ $L(topOperateItem.top_at ? '取消置顶' : '置顶该聊天') }}
</DropdownItem>
<DropdownItem @click.native="updateRead('read')" v-if="topOperateItem.unread > 0">
<DropdownItem @click.native="updateRead('read')" v-if="$A.getDialogUnread(topOperateItem) > 0">
{{ $L('标记已读') }}
</DropdownItem>
<DropdownItem @click.native="updateRead('unread')" v-else>
@ -213,21 +213,22 @@ export default {
return function (type) {
let num = 0;
this.cacheDialogs.some((dialog) => {
if (dialog.unread) {
let unread = $A.getDialogUnread(dialog);
if (unread) {
switch (type) {
case 'project':
case 'task':
if (type == dialog.group_type) {
num += dialog.unread;
num += unread;
}
break;
case 'user':
if (type == dialog.type) {
num += dialog.unread;
num += unread;
}
break;
default:
num += dialog.unread;
num += unread;
break;
}
}
@ -286,7 +287,7 @@ export default {
onActive(type) {
if (this.dialogActive == type) {
//
const dialog = this.dialogList.find(({unread}) => unread > 0)
const dialog = this.dialogList.find(dialog => $A.getDialogUnread(dialog) > 0)
if (dialog) {
$A.scrollToView(this.$refs[`dialog_${dialog.id}`][0], {
behavior: 'smooth',
@ -322,7 +323,7 @@ export default {
},
filterDialog(dialog) {
if (dialog.unread > 0 || dialog.id == this.dialogId || dialog.top_at) {
if ($A.getDialogUnread(dialog) > 0 || dialog.id == this.dialogId || dialog.top_at) {
return true
}
if (dialog.name === undefined) {

View File

@ -2085,6 +2085,7 @@ export default {
let dialog = state.cacheDialogs.find(({id}) => id == data.dialog_id);
if (dialog && dialog.unread > 0) {
dialog.unread--
dialog.is_mark_unread = 0
dispatch("saveDialog", dialog)
}
//