diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php
index 981484237..aa5cdaa0a 100755
--- a/app/Http/Controllers/Api/DialogController.php
+++ b/app/Http/Controllers/Api/DialogController.php
@@ -1042,6 +1042,53 @@ class DialogController extends AbstractController
return $msg->toggleTodoMsg($user->userid);
}
+ /**
+ * @api {get} api/dialog/msg/done 19. 完成待办
+ *
+ * @apiDescription 需要token身份
+ * @apiVersion 1.0.0
+ * @apiGroup dialog
+ * @apiName msg__done
+ *
+ * @apiParam {Number} id 待办数据ID
+ *
+ * @apiSuccess {Number} ret 返回状态码(1正确、0错误)
+ * @apiSuccess {String} msg 返回信息(错误描述)
+ * @apiSuccess {Object} data 返回数据
+ */
+ public function msg__done()
+ {
+ $user = User::auth();
+ //
+ $id = intval(Request::input("id"));
+ //
+ $add = [];
+ $todo = WebSocketDialogMsgTodo::whereId($id)->whereUserid($user->userid)->first();
+ if ($todo && empty($todo->done_at)) {
+ $todo->done_at = Carbon::now();
+ $todo->save();
+ //
+ $msg = WebSocketDialogMsg::find($todo->msg_id);
+ if ($msg) {
+ $res = WebSocketDialogMsg::sendMsg(null, $todo->dialog_id, 'todo', [
+ 'action' => 'done',
+ 'data' => [
+ 'id' => $msg->id,
+ 'type' => $msg->type,
+ 'msg' => $msg->msg,
+ ]
+ ]);
+ if (Base::isSuccess($res)) {
+ $add = $res['data'];
+ }
+ }
+ }
+ //
+ return Base::retSuccess("待办已完成", [
+ 'add' => $add ?: null
+ ]);
+ }
+
/**
* @api {get} api/dialog/group/add 21. 新增群组
*
diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php
index 571eacb2e..f175466c8 100644
--- a/app/Models/WebSocketDialog.php
+++ b/app/Models/WebSocketDialog.php
@@ -81,7 +81,7 @@ class WebSocketDialog extends AbstractModel
$builder = WebSocketDialogUser::whereDialogId($this->id);
$this->people = $builder->count();
// 有待办
- $this->has_todo = WebSocketDialogMsgTodo::whereDialogId($this->id)->whereDoneAt(null)->exists();
+ $this->has_todo = WebSocketDialogMsgTodo::whereDialogId($this->id)->whereUserid($userid)->whereDoneAt(null)->exists();
}
// 对方信息
$this->dialog_user = null;
diff --git a/app/Models/WebSocketDialogMsg.php b/app/Models/WebSocketDialogMsg.php
index 83c3a982e..33837ee26 100644
--- a/app/Models/WebSocketDialogMsg.php
+++ b/app/Models/WebSocketDialogMsg.php
@@ -264,7 +264,7 @@ class WebSocketDialogMsg extends AbstractModel
*/
public function toggleTagMsg($sender)
{
- if ($this->type === 'tag') {
+ if (in_array($this->type, ['tag', 'todo', 'notice'])) {
return Base::retError('此消息不支持标注');
}
$before = $this->tag;
@@ -289,13 +289,13 @@ class WebSocketDialogMsg extends AbstractModel
if (Base::isSuccess($res)) {
$data['add'] = $res['data'];
$dialog = WebSocketDialog::find($this->dialog_id);
- $dialog->pushMsg('update', $data['update']);
+ $dialog->pushMsg('update', $resData);
} else {
$this->tag = $before;
$this->save();
}
//
- return Base::retSuccess('sucess', $data);
+ return Base::retSuccess($this->tag ? '标注成功' : '取消成功', $data);
}
/**
@@ -305,7 +305,7 @@ class WebSocketDialogMsg extends AbstractModel
*/
public function toggleTodoMsg($sender)
{
- if ($this->type === 'todo') {
+ if (in_array($this->type, ['tag', 'todo', 'notice'])) {
return Base::retError('此消息不支持社待办');
}
$before = $this->todo;
@@ -330,7 +330,7 @@ class WebSocketDialogMsg extends AbstractModel
if (Base::isSuccess($res)) {
$data['add'] = $res['data'];
$dialog = WebSocketDialog::find($this->dialog_id);
- $dialog->pushMsg('update', array_merge($data['update'], ['dialog_id' => $this->dialog_id]));
+ $dialog->pushMsg('update', array_merge($resData, ['dialog_id' => $this->dialog_id]));
//
if ($this->todo) {
$userids = $dialog->dialogUser->pluck('userid')->toArray();
@@ -349,7 +349,7 @@ class WebSocketDialogMsg extends AbstractModel
$this->save();
}
//
- return Base::retSuccess('sucess', $data);
+ return Base::retSuccess($this->todo ? '设置成功' : '取消成功', $data);
}
/**
@@ -422,6 +422,8 @@ class WebSocketDialogMsg extends AbstractModel
]
]);
}
+ //
+ WebSocketDialogMsgTodo::whereMsgId($this->id)->delete();
});
}
@@ -455,7 +457,7 @@ class WebSocketDialogMsg extends AbstractModel
$action = $data['msg']['action'] === 'remove' ? '取消标注' : '标注';
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
case 'todo':
- $action = $data['msg']['action'] === 'remove' ? '取消待办' : '设待办';
+ $action = $data['msg']['action'] === 'remove' ? '取消待办' : ($data['msg']['action'] === 'done' ? '完成了' : '设待办');
return "[{$action}] {$this->previewMsg(false, $data['msg']['data'])}";
case 'notice':
return $data['msg']['notice'];
diff --git a/resources/assets/js/functions/web.js b/resources/assets/js/functions/web.js
index b47a452de..5e62e9edf 100755
--- a/resources/assets/js/functions/web.js
+++ b/resources/assets/js/functions/web.js
@@ -493,7 +493,7 @@
case 'tag':
return `[${$A.L(data.msg.action === 'remove' ? '取消标注' : '标注')}] ${$A.getMsgSimpleDesc(data.msg.data)}`
case 'todo':
- return `[${$A.L(data.msg.action === 'remove' ? '取消待办' : '设待办')}] ${$A.getMsgSimpleDesc(data.msg.data)}`
+ return `[${$A.L(data.msg.action === 'remove' ? '取消待办' : (data.msg.action === 'done' ? '完成了' : '设待办'))}] ${$A.getMsgSimpleDesc(data.msg.data)}`
case 'notice':
return data.msg.notice
default:
diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue
index a201bed19..3bf554dc3 100644
--- a/resources/assets/js/pages/manage.vue
+++ b/resources/assets/js/pages/manage.vue
@@ -510,6 +510,9 @@ export default {
},
msgUnreadMention() {
+ if (this.cacheDialogs.find(item => item.has_todo)) {
+ return this.$L("待办")
+ }
let num = 0;
let mention = 0;
this.cacheDialogs.some(dialog => {
diff --git a/resources/assets/js/pages/manage/components/DialogItem.vue b/resources/assets/js/pages/manage/components/DialogItem.vue
index b0c6e12dc..d3eecab5b 100644
--- a/resources/assets/js/pages/manage/components/DialogItem.vue
+++ b/resources/assets/js/pages/manage/components/DialogItem.vue
@@ -7,7 +7,7 @@
- {{$L(source.msg.action === 'remove' ? '取消待办' : '设待办')}}
+ {{$L(source.msg.action === 'remove' ? '取消待办' : (source.msg.action === 'done' ? '完成了' : '设待办'))}}
"{{$A.getMsgSimpleDesc(source.msg.data)}}"
diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue
index ac709849d..4d3d68999 100644
--- a/resources/assets/js/pages/manage/components/DialogWrapper.vue
+++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue
@@ -124,8 +124,9 @@
@@ -923,34 +924,77 @@ export default {
},
onPositionId(position_id, msg_id = 0) {
- if (position_id === 0) {
- return
- }
- const index = this.allMsgs.findIndex(item => item.id === position_id)
- if (index > -1) {
- this.onToIndex(index)
- } else {
- if (msg_id > 0) {
- this.$store.dispatch("setLoad", {
- key: `msg-${msg_id}`,
- delay: 600
+ return new Promise(resolve => {
+ if (position_id === 0) {
+ return
+ }
+ const index = this.allMsgs.findIndex(item => item.id === position_id)
+ if (index > -1) {
+ this.onToIndex(index)
+ resolve()
+ } else {
+ if (msg_id > 0) {
+ this.$store.dispatch("setLoad", {
+ key: `msg-${msg_id}`,
+ delay: 600
+ })
+ }
+ this.msgType = '';
+ this.preventToBottom = true;
+ this.$store.dispatch("getDialogMsgs", {
+ dialog_id: this.dialogId,
+ msg_id: this.msgId,
+ position_id
+ }).finally(_ => {
+ const index = this.allMsgs.findIndex(item => item.id === position_id)
+ if (index > -1) {
+ this.onToIndex(index)
+ resolve()
+ }
+ if (msg_id > 0) {
+ this.$store.dispatch("cancelLoad", `msg-${msg_id}`)
+ }
+ this.preventToBottom = false;
})
}
- this.msgType = '';
- this.preventToBottom = true;
- this.$store.dispatch("getDialogMsgs", {
- dialog_id: this.dialogId,
- msg_id: this.msgId,
- position_id
+ })
+ },
+
+ onClickTodo(item, event) {
+ if (event && event.target.classList.contains('todo-done')) {
+ // 完成
+ this.$store.dispatch("setLoad", {
+ key: `msg-${item.msg_id}`,
+ delay: 600
+ })
+ this.$store.dispatch("call", {
+ url: 'dialog/msg/done',
+ data: {
+ id: item.id,
+ },
+ }).then(({data}) => {
+ this.$store.dispatch("saveDialogTodo", {
+ id: item.id,
+ done_at: $A.formatDate("Y-m-d H:i:s")
+ })
+ if (data.add) {
+ this.sendSuccess(data.add)
+ }
+ if (this.todoList.length === 0) {
+ this.$store.dispatch("getDialogTodo", item.dialog_id)
+ }
+ }).catch(({msg}) => {
+ $A.modalError(msg)
}).finally(_ => {
- const index = this.allMsgs.findIndex(item => item.id === position_id)
- if (index > -1) {
- this.onToIndex(index)
- }
- if (msg_id > 0) {
- this.$store.dispatch("cancelLoad", `msg-${msg_id}`)
- }
- this.preventToBottom = false;
+ this.$store.dispatch("cancelLoad", `msg-${item.msg_id}`)
+ });
+ } else {
+ // 定位
+ this.onPositionId(item.msg_id).then(_ => {
+ this.$store.dispatch("saveDialogTodo", {
+ id: item.id,
+ click: true
+ })
})
}
},
diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue
index 9b239c932..37875d483 100644
--- a/resources/assets/js/pages/manage/messenger.vue
+++ b/resources/assets/js/pages/manage/messenger.vue
@@ -60,6 +60,7 @@
+
[{{$L('待办')}}]
[@{{$A.getDialogMention(dialog)}}]
{{$L(tag.text)}}
@@ -215,6 +216,9 @@ export default {
if (a.top_at || b.top_at) {
return $A.Date(b.top_at) - $A.Date(a.top_at);
}
+ if (a.has_todo || b.has_todo) {
+ return (b.has_todo ? 1 : 0) - (a.has_todo ? 1 : 0);
+ }
return $A.Date(b.last_at) - $A.Date(a.last_at);
});
}
@@ -275,6 +279,9 @@ export default {
if (a.top_at || b.top_at) {
return $A.Date(b.top_at) - $A.Date(a.top_at);
}
+ if (a.has_todo || b.has_todo) {
+ return (b.has_todo ? 1 : 0) - (a.has_todo ? 1 : 0);
+ }
return $A.Date(b.last_at) - $A.Date(a.last_at);
})
},
diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js
index fc64362f9..35fbc8b04 100644
--- a/resources/assets/js/store/actions.js
+++ b/resources/assets/js/store/actions.js
@@ -2045,7 +2045,7 @@ export default {
has_todo: true
});
state.dialogTodos = state.dialogTodos.filter(item => item.dialog_id != dialog_id)
- state.dialogTodos.push(...data)
+ dispatch("saveDialogTodo", data)
} else {
dispatch("saveDialog", {
id: dialog_id,
@@ -2151,6 +2151,44 @@ export default {
}
},
+ /**
+ * 保存待办数据
+ * @param state
+ * @param dispatch
+ * @param data
+ */
+ saveDialogTodo({state, dispatch}, data) {
+ $A.execMainDispatch("saveDialogTodo", data)
+ //
+ if ($A.isArray(data)) {
+ data.forEach(item => {
+ dispatch("saveDialogTodo", item)
+ });
+ } else if ($A.isJson(data)) {
+ const index = state.dialogTodos.findIndex(item => item.id == data.id);
+ if (index > -1) {
+ state.dialogTodos.splice(index, 1, Object.assign({}, state.dialogTodos[index], data));
+ } else {
+ state.dialogTodos.push(data);
+ }
+ }
+ },
+
+ /**
+ * 忘记待办数据
+ * @param state
+ * @param dispatch
+ * @param msg_id
+ */
+ forgetDialogTodoForMsgId({state, dispatch}, msg_id) {
+ $A.execMainDispatch("forgetDialogTodoForMsgId", msg_id)
+ //
+ const index = state.dialogTodos.findIndex(item => item.msg_id == msg_id);
+ if (index > -1) {
+ state.dialogTodos.splice(index, 1);
+ }
+ },
+
/** *****************************************************************************************/
/** ************************************** 消息 **********************************************/
/** *****************************************************************************************/
@@ -2205,6 +2243,7 @@ export default {
state.dialogMsgs.splice(index, 1);
}
})
+ dispatch("forgetDialogTodoForMsgId", msg_id)
},
/**
@@ -2245,7 +2284,7 @@ export default {
}
if ($A.isArray(resData.todo)) {
state.dialogTodos = state.dialogTodos.filter(item => item.dialog_id != data.dialog_id)
- state.dialogTodos.push(...resData.todo)
+ dispatch("saveDialogTodo", resData.todo)
}
//
dispatch("saveDialogMsg", resData.list)
diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss
index a4becfacd..08782a274 100644
--- a/resources/assets/sass/pages/components/dialog-wrapper.scss
+++ b/resources/assets/sass/pages/components/dialog-wrapper.scss
@@ -1013,14 +1013,37 @@
list-style: none;
margin-right: 8px;
background-color: #f0f1f3;
- padding: 0 8px;
- border-radius: 6px;
- line-height: 24px;
- max-width: 150px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
+ padding: 0 12px;
+ border-radius: 13px;
+ line-height: 26px;
+ font-size: 13px;
cursor: pointer;
+ display: flex;
+ align-items: center;
+ .todo-desc {
+ max-width: 150px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .todo-done {
+ flex-shrink: 1;
+ font-weight: 500;
+ color: $primary-color;
+ position: relative;
+ margin-left: 7px;
+ padding-left: 8px;
+ &:before {
+ content: "";
+ position: absolute;
+ top: 50%;
+ left: 0;
+ height: 10px;
+ width: 1px;
+ transform: translateY(-50%) scaleX(0.5);
+ background-color: #cccccc;
+ }
+ }
}
}
}
@@ -1419,6 +1442,17 @@
background-color: #f8f8f8;
padding: 8px 10px;
margin-bottom: 0;
+ .chat-todo {
+ padding-top: 0;
+ > ul {
+ > li {
+ background-color: #ffffff;
+ .todo-desc {
+ max-width: 120px;
+ }
+ }
+ }
+ }
.chat-mute {
background-color: #ffffff;
}