perf: 支持修改消息待办

This commit is contained in:
kuaifan 2024-05-11 10:45:31 +09:00
parent 80fe978454
commit 2bda6bf668
6 changed files with 169 additions and 74 deletions

View File

@ -1765,7 +1765,9 @@ class DialogController extends AbstractController
* @apiParam {String} type 设待办对象 * @apiParam {String} type 设待办对象
* - all: 会话全部成员(默认) * - all: 会话全部成员(默认)
* - user: 会话指定成员 * - user: 会话指定成员
* @apiParam {Array} userids 会员ID组type=user有效格式: [userid1, userid2, userid3] * @apiParam {Array} userids 会员ID组
* - type=user 有效,格式: [userid1, userid2, userid3]
* - 可通过 type=user userids:[] 一起使用来清除所有人的待办
* *
* @apiSuccess {Number} ret 返回状态码1正确、0错误 * @apiSuccess {Number} ret 返回状态码1正确、0错误
* @apiSuccess {String} msg 返回信息(错误描述) * @apiSuccess {String} msg 返回信息(错误描述)
@ -1773,26 +1775,24 @@ class DialogController extends AbstractController
*/ */
public function msg__todo() public function msg__todo()
{ {
Base::checkClientVersion('0.37.18');
$user = User::auth(); $user = User::auth();
// //
$msg_id = intval(Request::input("msg_id")); $msg_id = intval(Request::input("msg_id"));
$type = trim(Request::input("type", "all")); $type = trim(Request::input("type", "all"));
$userids = Request::input('userids'); $userids = Request::input('userids');
// //
if ($type === 'user') {
if (empty($userids)) {
return Base::retError("选择指定成员");
}
} else {
$userids = [];
}
//
$msg = WebSocketDialogMsg::whereId($msg_id)->first(); $msg = WebSocketDialogMsg::whereId($msg_id)->first();
if (empty($msg)) { if (empty($msg)) {
return Base::retError("消息不存在或已被删除"); return Base::retError("消息不存在或已被删除");
} }
WebSocketDialog::checkDialog($msg->dialog_id); $dialog = WebSocketDialog::checkDialog($msg->dialog_id);
// //
if ($type === 'all') {
$userids = $dialog->dialogUser->pluck('userid')->toArray();
} else {
$userids = is_array($userids) ? $userids : [];
}
return $msg->toggleTodoMsg($user->userid, $userids); return $msg->toggleTodoMsg($user->userid, $userids);
} }

View File

@ -320,41 +320,54 @@ class WebSocketDialogMsg extends AbstractModel
if (in_array($this->type, ['tag', 'todo', 'notice'])) { if (in_array($this->type, ['tag', 'todo', 'notice'])) {
return Base::retError('此消息不支持设待办'); return Base::retError('此消息不支持设待办');
} }
if ($this->todo && $this->todo != $sender) { $current = WebSocketDialogMsgTodo::whereMsgId($this->id)->pluck('userid')->toArray();
return Base::retError('仅支持设此待办人员【' . User::userid2nickname($this->todo) . '】取消'); $cancel = array_diff($current, $userids);
} $setup = array_diff($userids, $current);
$before = $this->todo; //
$this->todo = $before ? 0 : $sender; $this->todo = $setup || count($current) > count($cancel) ? $sender : 0;
$this->save(); $this->save();
$resData = [ $upData = [
'id' => $this->id, 'id' => $this->id,
'todo' => $this->todo, 'todo' => $this->todo,
'dialog_id' => $this->dialog_id,
]; ];
$dialog = WebSocketDialog::find($this->dialog_id);
$dialog->pushMsg('update', $upData);
// //
$data = [ $retData = [
'update' => $resData 'add' => [],
'update' => $upData
]; ];
if ($cancel) {
$res = self::sendMsg(null, $this->dialog_id, 'todo', [ $res = self::sendMsg(null, $this->dialog_id, 'todo', [
'action' => $this->todo ? 'add' : 'remove', 'action' => 'remove',
'data' => [ 'data' => [
'id' => $this->id, 'id' => $this->id,
'type' => $this->type, 'type' => $this->type,
'msg' => $this->quoteTextMsg(), 'msg' => $this->quoteTextMsg(),
'userids' => implode(",", $userids), 'userids' => implode(",", $cancel),
] ]
], $sender); ], $sender);
if (Base::isSuccess($res)) { if (Base::isSuccess($res)) {
$data['add'] = $res['data']; $retData['add'][] = $res['data'];
$dialog = WebSocketDialog::find($this->dialog_id); WebSocketDialogMsgTodo::whereMsgId($this->id)->whereIn('userid', $cancel)->delete();
$dialog->pushMsg('update', array_merge($resData, ['dialog_id' => $this->dialog_id]));
//
if ($this->todo) {
$useridList = $dialog->dialogUser->pluck('userid')->toArray();
foreach ($useridList as $userid) {
if ($userids && !in_array($userid, $userids)) {
continue;
} }
if (empty($userid)) { }
if ($setup) {
$res = self::sendMsg(null, $this->dialog_id, 'todo', [
'action' => 'add',
'data' => [
'id' => $this->id,
'type' => $this->type,
'msg' => $this->quoteTextMsg(),
'userids' => implode(",", $setup),
]
], $sender);
if (Base::isSuccess($res)) {
$retData['add'][] = $res['data'];
$useridList = $dialog->dialogUser->pluck('userid')->toArray();
foreach ($setup as $userid) {
if (!in_array($userid, $useridList)) {
continue; continue;
} }
WebSocketDialogMsgTodo::createInstance([ WebSocketDialogMsgTodo::createInstance([
@ -363,15 +376,10 @@ class WebSocketDialogMsg extends AbstractModel
'userid' => $userid, 'userid' => $userid,
])->saveOrIgnore(); ])->saveOrIgnore();
} }
} else {
WebSocketDialogMsgTodo::whereMsgId($this->id)->delete();
} }
} else {
$this->todo = $before;
$this->save();
} }
// //
return Base::retSuccess($this->todo ? '设置成功' : '取消成功', $data); return Base::retSuccess($this->todo ? '设置成功' : '取消成功', $retData);
} }
/** /**

View File

@ -53,6 +53,7 @@
@on-reply-list="onReplyList" @on-reply-list="onReplyList"
@on-error="onError" @on-error="onError"
@on-emoji="onEmoji" @on-emoji="onEmoji"
@on-other="onOther"
@on-show-emoji-user="onShowEmojiUser"/> @on-show-emoji-user="onShowEmojiUser"/>
</template> </template>
</div> </div>
@ -258,6 +259,10 @@ export default {
this.dispatch("on-emoji", data) this.dispatch("on-emoji", data)
}, },
onOther(data) {
this.dispatch("on-other", data)
},
onShowEmojiUser(data) { onShowEmojiUser(data) {
this.dispatch("on-show-emoji-user", data) this.dispatch("on-show-emoji-user", data)
}, },

View File

@ -196,7 +196,10 @@
:placement="isRightMsg ? 'bottom-end' : 'bottom-start'"> :placement="isRightMsg ? 'bottom-end' : 'bottom-start'">
<div class="read-poptip-content"> <div class="read-poptip-content">
<Scrollbar class-name="read"> <Scrollbar class-name="read">
<div class="read-title"><em>{{ todoDoneList.length }}</em>{{ $L('完成') }}</div> <div class="read-title">
<em>{{ todoDoneList.length }}</em>
{{ $L('完成') }}
</div>
<ul> <ul>
<li v-for="item in todoDoneList"> <li v-for="item in todoDoneList">
<UserAvatar :userid="item.userid" :size="26" showName/> <UserAvatar :userid="item.userid" :size="26" showName/>
@ -204,7 +207,12 @@
</ul> </ul>
</Scrollbar> </Scrollbar>
<Scrollbar class-name="unread"> <Scrollbar class-name="unread">
<div class="read-title"><em>{{ todoUndoneList.length }}</em>{{ $L('待办') }}</div> <div class="read-title">
<em>{{ todoUndoneList.length }}</em>
{{ $L('待办') }}
<span class="space"></span>
<Button type="primary" size="small" @click="handleTodoAdd">{{ $L('添加') }}</Button>
</div>
<ul> <ul>
<li v-for="item in todoUndoneList"> <li v-for="item in todoUndoneList">
<UserAvatar :userid="item.userid" :size="26" showName/> <UserAvatar :userid="item.userid" :size="26" showName/>
@ -240,7 +248,10 @@
:placement="isRightMsg ? 'bottom-end' : 'bottom-start'"> :placement="isRightMsg ? 'bottom-end' : 'bottom-start'">
<div class="read-poptip-content"> <div class="read-poptip-content">
<Scrollbar class-name="read"> <Scrollbar class-name="read">
<div class="read-title"><em>{{ readList.length }}</em>{{ $L('已读') }}</div> <div class="read-title">
<em>{{ readList.length }}</em>
{{ $L('已读') }}
</div>
<ul> <ul>
<li v-for="item in readList"> <li v-for="item in readList">
<UserAvatar :userid="item.userid" :size="26" showName/> <UserAvatar :userid="item.userid" :size="26" showName/>
@ -248,7 +259,10 @@
</ul> </ul>
</Scrollbar> </Scrollbar>
<Scrollbar class-name="unread"> <Scrollbar class-name="unread">
<div class="read-title"><em>{{ unreadList.length }}</em>{{ $L('未读') }}</div> <div class="read-title">
<em>{{ unreadList.length }}</em>
{{ $L('未读') }}
</div>
<ul> <ul>
<li v-for="item in unreadList"> <li v-for="item in unreadList">
<UserAvatar :userid="item.userid" :size="26" showName/> <UserAvatar :userid="item.userid" :size="26" showName/>
@ -488,6 +502,17 @@ export default {
}); });
}, },
handleTodoAdd() {
this.$refs.todo.doClose();
this.$emit("on-other", {
event: 'todoAdd',
data: {
msg_id: this.msgData.id,
userids: this.todoList.map(({userid}) => userid)
}
})
},
openReadPercentage() { openReadPercentage() {
if (this.percentageLoad > 0) { if (this.percentageLoad > 0) {
return; return;

View File

@ -200,6 +200,7 @@
@on-reply-list="onReplyList" @on-reply-list="onReplyList"
@on-error="onError" @on-error="onError"
@on-emoji="onEmoji" @on-emoji="onEmoji"
@on-other="onOther"
@on-show-emoji-user="onShowEmojiUser"> @on-show-emoji-user="onShowEmojiUser">
<template #header v-if="!isChildComponent"> <template #header v-if="!isChildComponent">
<div class="dialog-item head-box"> <div class="dialog-item head-box">
@ -486,6 +487,7 @@
@on-view-file="onViewFile" @on-view-file="onViewFile"
@on-down-file="onDownFile" @on-down-file="onDownFile"
@on-emoji="onEmoji" @on-emoji="onEmoji"
@on-other="onOther"
simpleView/> simpleView/>
</Scrollbar> </Scrollbar>
</div> </div>
@ -554,6 +556,15 @@
<Button type="primary" :loading="todoSettingLoad > 0" @click="onTodo('submit')">{{$L('确定')}}</Button> <Button type="primary" :loading="todoSettingLoad > 0" @click="onTodo('submit')">{{$L('确定')}}</Button>
</div> </div>
</Modal> </Modal>
<UserSelect
v-if="todoSpecifyShow"
ref="todoSpecifySelect"
v-model="todoSpecifyData.userids"
:dialog-id="dialogId"
:title="$L('选择指定成员')"
module
border
:before-submit="onTodoSpecify"/>
<!--群设置--> <!--群设置-->
<DrawerOverlay <DrawerOverlay
@ -629,6 +640,7 @@
@on-view-file="onViewFile" @on-view-file="onViewFile"
@on-down-file="onDownFile" @on-down-file="onDownFile"
@on-emoji="onEmoji" @on-emoji="onEmoji"
@on-other="onOther"
simpleView/> simpleView/>
<Button class="original-button" icon="md-exit" type="text" :loading="todoViewPosLoad" @click="onPosTodo">{{ $L("回到原文") }}</Button> <Button class="original-button" icon="md-exit" type="text" :loading="todoViewPosLoad" @click="onPosTodo">{{ $L("回到原文") }}</Button>
</template> </template>
@ -806,6 +818,11 @@ export default {
userids: [], userids: [],
quick_value: [], quick_value: [],
}, },
todoSpecifyShow: false,
todoSpecifyData: {
type: 'user',
userids: [],
},
todoViewLoad: false, todoViewLoad: false,
todoViewPosLoad: false, todoViewPosLoad: false,
@ -3395,6 +3412,19 @@ export default {
this.respondShow = true this.respondShow = true
}, },
onOther({event, data}) {
if (this.operateVisible) {
return
}
if (event === 'todoAdd') {
this.todoSpecifyData = Object.assign(this.todoSpecifyData, data)
this.todoSpecifyShow = true
this.$nextTick(_ => {
this.$refs.todoSpecifySelect.onSelection()
})
}
},
onTag() { onTag() {
if (this.operateVisible) { if (this.operateVisible) {
return return
@ -3459,6 +3489,19 @@ export default {
}).finally(_ => { }).finally(_ => {
this.todoSettingLoad-- this.todoSettingLoad--
}) })
} else {
if (this.operateItem.todo) {
$A.modalConfirm({
content: "你确定取消待办吗?",
cancelText: '取消',
okText: '确定',
loading: true,
onOk: () => this.onTodoSubmit({
type: 'user',
userids: [],
msg_id: this.operateItem.id,
})
});
} else { } else {
const quickList = {} const quickList = {}
quickList[this.userId] = this.userId quickList[this.userId] = this.userId
@ -3485,20 +3528,23 @@ export default {
quick_value: [], quick_value: [],
quick_list: Object.values(quickList), quick_list: Object.values(quickList),
} }
if (this.operateItem.todo) {
$A.modalConfirm({
content: "你确定取消待办吗?",
cancelText: '取消',
okText: '确定',
loading: true,
onOk: () => this.onTodoSubmit(this.todoSettingData)
});
} else {
this.todoSettingShow = true this.todoSettingShow = true
} }
} }
}, },
onTodoSpecify() {
return new Promise((resolve, reject) => {
this.onTodoSubmit(this.todoSpecifyData).then(msg => {
$A.messageSuccess(msg)
resolve()
}).catch(e => {
$A.messageError(e)
reject()
})
});
},
onTodoSubmit(data) { onTodoSubmit(data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.$store.dispatch("setLoad", { this.$store.dispatch("setLoad", {
@ -3506,6 +3552,7 @@ export default {
delay: 600 delay: 600
}) })
this.$store.dispatch("call", { this.$store.dispatch("call", {
method: 'post',
url: 'dialog/msg/todo', url: 'dialog/msg/todo',
data, data,
}).then(({data, msg}) => { }).then(({data, msg}) => {

View File

@ -2068,12 +2068,22 @@ body:not(.window-touch) {
top: 0; top: 0;
z-index: 10; z-index: 10;
background: #ffffff; background: #ffffff;
display: flex;
align-items: center;
> em { > em {
font-size: 18px; font-size: 18px;
font-weight: 600; font-weight: 600;
font-style: normal; font-style: normal;
padding-right: 6px; padding-right: 6px;
} }
> span.space {
flex: 1;
height: 1px;
}
> button {
transform: scale(0.96);
transform-origin: right center;
}
} }
ul > li { ul > li {