diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index f9726bea4..2a76cb5d1 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -503,6 +503,7 @@ class DialogController extends AbstractController $builder = WebSocketDialogMsg::select([ 'web_socket_dialog_msgs.*', 'read.mention', + 'read.dot', 'read.read_at', ])->leftJoin('web_socket_dialog_msg_reads as read', function ($leftJoin) use ($user) { $leftJoin @@ -620,6 +621,7 @@ class DialogController extends AbstractController $builder = WebSocketDialogMsg::select([ 'web_socket_dialog_msgs.*', 'read.mention', + 'read.dot', 'read.read_at', ])->leftJoin('web_socket_dialog_msg_reads as read', function ($leftJoin) use ($user) { $leftJoin @@ -718,6 +720,39 @@ class DialogController extends AbstractController return Base::retSuccess('success', $msg); } + /** + * @api {get} api/dialog/msg/dot 16. 聊天消息去除点 + * + * @apiDescription 需要token身份 + * @apiVersion 1.0.0 + * @apiGroup dialog + * @apiName msg__dot + * + * @apiParam {Number} id 消息ID + * + * @apiSuccess {Number} ret 返回状态码(1正确、0错误) + * @apiSuccess {String} msg 返回信息(错误描述) + * @apiSuccess {Object} data 返回数据 + */ + public function msg__dot() + { + $user = User::auth(); + // + $id = intval(Request::input('id')); + // + $msg = WebSocketDialogMsg::find($id); + if (empty($msg)) { + return Base::retError("消息不存在或已被删除"); + } + // + WebSocketDialogMsgRead::whereMsgId($id)->whereUserid($user->userid)->change(['dot' => 0]); + // + return Base::retSuccess('success', [ + 'id' => $msg->id, + 'dot' => 0, + ]); + } + /** * @api {get} api/dialog/msg/read 16. 已读聊天消息 * diff --git a/app/Tasks/WebSocketDialogMsgTask.php b/app/Tasks/WebSocketDialogMsgTask.php index 39657acf3..e1c45133b 100644 --- a/app/Tasks/WebSocketDialogMsgTask.php +++ b/app/Tasks/WebSocketDialogMsgTask.php @@ -112,24 +112,28 @@ class WebSocketDialogMsgTask extends AbstractTask if ($userid == $msg->userid) { $array[$userid] = [ 'userid' => $userid, - 'mention' => false, + 'mention' => 0, 'silence' => $silence, + 'dot' => 0, 'updated' => $updated, ]; } else { $mention = array_intersect([0, $userid], $mentions) ? 1 : 0; $silence = $mention ? false : $silence; + $dot = $msg->type === 'record' ? 1 : 0; WebSocketDialogMsgRead::createInstance([ 'dialog_id' => $msg->dialog_id, 'msg_id' => $msg->id, 'userid' => $userid, 'mention' => $mention, 'silence' => $silence, + 'dot' => $dot, ])->saveOrIgnore(); $array[$userid] = [ 'userid' => $userid, 'mention' => $mention, 'silence' => $silence, + 'dot' => $dot, 'updated' => $updated, ]; // 机器人收到消处理 @@ -169,6 +173,7 @@ class WebSocketDialogMsgTask extends AbstractTask 'silence' => $item['silence'] ? 1 : 0, 'data' => array_merge($msg->toArray(), [ 'mention' => $item['mention'], + 'dot' => $item['dot'], 'user_at' => Carbon::parse($item['updated'])->toDateTimeString('millisecond'), 'user_ms' => Carbon::parse($item['updated'])->valueOf(), ]), diff --git a/database/migrations/2024_05_01_105735_add_web_socket_dialog_msg_reads_dot.php b/database/migrations/2024_05_01_105735_add_web_socket_dialog_msg_reads_dot.php new file mode 100644 index 000000000..3d8820c54 --- /dev/null +++ b/database/migrations/2024_05_01_105735_add_web_socket_dialog_msg_reads_dot.php @@ -0,0 +1,34 @@ +integer('dot')->nullable()->default(0)->after('after')->comment('红点标记'); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('web_socket_dialog_msg_reads', function (Blueprint $table) { + $table->dropColumn("dot"); + }); + } +} diff --git a/resources/assets/js/pages/manage/components/DialogView.vue b/resources/assets/js/pages/manage/components/DialogView.vue index e1a188fdb..b316af896 100644 --- a/resources/assets/js/pages/manage/components/DialogView.vue +++ b/resources/assets/js/pages/manage/components/DialogView.vue @@ -8,6 +8,7 @@
@@ -329,7 +330,8 @@ export default { emojiUsersNum: 5, voteData: {}, - unfoldWordChainData: [] + dotClicks: [], + unfoldWordChainData: [], } }, @@ -390,8 +392,11 @@ export default { }, headClass() { - const {reply_id, type, msg, emoji} = this.msgData; + const {id, reply_id, type, msg, emoji, dot} = this.msgData; const array = []; + if (dot && !this.dotClicks.includes(id)) { + array.push('dot') + } if (reply_id === 0 && $A.arrayLength(emoji) === 0) { if (type === 'text') { if (/^]*?>$/.test(msg.text) @@ -447,6 +452,13 @@ export default { this.$emit("on-longpress", {event, el, msgData: this.msgData}) }, + handleClick() { + if (this.msgData.dot) { + this.dotClicks.push(this.msgData.id); + this.$store.dispatch("dialogMsgDot", this.msgData); + } + }, + openTodo() { if (this.todoLoad > 0) { return; diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 77a2270f6..e21b88273 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -3262,6 +3262,31 @@ export default { }, 50); }, + /** + * 消息去除点 + * @param state + * @param dispatch + * @param data + */ + dialogMsgDot({state, dispatch}, data) { + if (!$A.isJson(data)) { + return; + } + if (!data.dot) { + return; + } + data.dot = 0; + // + dispatch("call", { + url: 'dialog/msg/dot', + data: { + id: data.id + } + }).then(({data}) => { + dispatch("saveDialog", data) + }); + }, + /** * 标记已读、未读 * @param state diff --git a/resources/assets/sass/pages/components/dialog-wrapper.scss b/resources/assets/sass/pages/components/dialog-wrapper.scss index 4e4529719..27523163f 100644 --- a/resources/assets/sass/pages/components/dialog-wrapper.scss +++ b/resources/assets/sass/pages/components/dialog-wrapper.scss @@ -685,6 +685,21 @@ background-color: transparent !important; } + &.dot { + position: relative; + &:after { + content: ""; + position: absolute; + top: 50%; + right: -16px; + width: 8px; + height: 8px; + border-radius: 50%; + background-color: #ed4014; + transform: translateY(-50%); + } + } + .dialog-reply { position: relative; padding-left: 9px; @@ -1553,6 +1568,13 @@ background-color: $primary-color; border-radius: 8px 2px 8px 8px; + &.dot { + &:after { + left: -16px; + right: unset; + } + } + .dialog-reply { color: #ffffff; &:after {