From 3aefe99bd94bb99474c214b0bcc14e74a25d3916 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Wed, 22 Jun 2022 15:49:55 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E9=A1=B9=E7=9B=AE=E7=BE=A4=E3=80=81?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E7=BE=A4=E5=8F=AF=E6=B7=BB=E5=8A=A0=E6=88=90?= =?UTF-8?q?=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Api/DialogController.php | 13 ++-- app/Models/Project.php | 4 +- app/Models/ProjectTask.php | 4 +- app/Models/WebSocketDialog.php | 60 ++++++++++++------- app/Models/WebSocketDialogUser.php | 4 ++ ..._socket_dialog_users_inviter_important.php | 48 +++++++++++++++ .../manage/components/DialogGroupInfo.vue | 37 +++++------- .../pages/manage/components/DialogWrapper.vue | 3 +- 8 files changed, 122 insertions(+), 51 deletions(-) create mode 100644 database/migrations/2022_06_22_151032_add_web_socket_dialog_users_inviter_important.php diff --git a/app/Http/Controllers/Api/DialogController.php b/app/Http/Controllers/Api/DialogController.php index cba039d22..814203e30 100755 --- a/app/Http/Controllers/Api/DialogController.php +++ b/app/Http/Controllers/Api/DialogController.php @@ -929,6 +929,8 @@ class DialogController extends AbstractController * @api {get} api/dialog/group/adduser 21. 添加群成员 * * @apiDescription 需要token身份 + * - 有群主时:只有群主可以邀请 + * - 没有群主时:群内成员都可以邀请 * @apiVersion 1.0.0 * @apiGroup dialog * @apiName group__adduser @@ -951,7 +953,7 @@ class DialogController extends AbstractController return Base::retError('请选择群成员'); } // - $dialog = WebSocketDialog::checkDialog($dialog_id, true); + $dialog = WebSocketDialog::checkDialog($dialog_id, "auto"); // $dialog->checkGroup(); $dialog->joinGroup($userids); @@ -963,6 +965,8 @@ class DialogController extends AbstractController * @api {get} api/dialog/group/deluser 22. 移出(退出)群成员 * * @apiDescription 需要token身份 + * - 只有群主、邀请人可以踢人 + * - 群主、任务人员、项目人员不可被踢或退出 * @apiVersion 1.0.0 * @apiGroup dialog * @apiName group__adduser @@ -993,10 +997,10 @@ class DialogController extends AbstractController return Base::retError('请选择群成员'); } // - $dialog = WebSocketDialog::checkDialog($dialog_id, $type === 'remove'); + $dialog = WebSocketDialog::checkDialog($dialog_id); // $dialog->checkGroup(); - $dialog->exitGroup($userids); + $dialog->exitGroup($userids, $type); $dialog->pushMsg("groupExit", null, $userids); return Base::retSuccess($type === 'remove' ? '移出成功' : '退出成功'); } @@ -1005,6 +1009,7 @@ class DialogController extends AbstractController * @api {get} api/dialog/group/disband 23. 解散群组 * * @apiDescription 需要token身份 + * - 只有群主且是个人类型群可以解散 * @apiVersion 1.0.0 * @apiGroup dialog * @apiName group__disband @@ -1023,7 +1028,7 @@ class DialogController extends AbstractController // $dialog = WebSocketDialog::checkDialog($dialog_id, true); // - $dialog->checkGroup(); + $dialog->checkGroup('user'); $dialog->deleteDialog(); $dialog->pushMsg("groupDelete"); return Base::retSuccess('解散成功'); diff --git a/app/Models/Project.php b/app/Models/Project.php index 7245b3a5f..34e5ee593 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -207,9 +207,11 @@ class Project extends AbstractModel WebSocketDialogUser::updateInsert([ 'dialog_id' => $this->dialog_id, 'userid' => $userid, + ], [ + 'important' => 1 ]); } - WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->delete(); + WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->whereImportant(1)->delete(); }); } diff --git a/app/Models/ProjectTask.php b/app/Models/ProjectTask.php index bf8bad66b..372e96858 100644 --- a/app/Models/ProjectTask.php +++ b/app/Models/ProjectTask.php @@ -876,9 +876,11 @@ class ProjectTask extends AbstractModel WebSocketDialogUser::updateInsert([ 'dialog_id' => $this->dialog_id, 'userid' => $userid, + ], [ + 'important' => 1 ]); } - WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->delete(); + WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->whereImportant(1)->delete(); }); } diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index 20cab2526..f9c4ca439 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -134,6 +134,8 @@ class WebSocketDialog extends AbstractModel WebSocketDialogUser::updateInsert([ 'dialog_id' => $this->id, 'userid' => $value, + ], [ + 'inviter' => User::userid(), ]); } } @@ -144,27 +146,34 @@ class WebSocketDialog extends AbstractModel /** * 退出聊天室 * @param int|array $userid 加入的会员ID或会员ID组 - * @return bool + * @param $type */ - public function exitGroup($userid) + public function exitGroup($userid, $type = 'exit') { - $builder = WebSocketDialogUser::whereDialogId($this->id); - if (is_array($userid)) { - $builder->whereIn('userid', $userid); - } else { - $builder->whereUserid($userid); - } - $builder->chunkById(100, function($list) { - /** @var WebSocketDialogUser $item */ - foreach ($list as $item) { - if ($item->userid == $this->owner_id) { - // 群主不可退出 - continue; - } - $item->delete(); + $typeDesc = $type === 'remove' ? '移出' : '退出'; + AbstractModel::transaction(function () use ($typeDesc, $type, $userid) { + $builder = WebSocketDialogUser::whereDialogId($this->id); + if (is_array($userid)) { + $builder->whereIn('userid', $userid); + } else { + $builder->whereUserid($userid); } + $builder->chunkById(100, function($list) use ($typeDesc, $type) { + /** @var WebSocketDialogUser $item */ + foreach ($list as $item) { + if ($type === 'remove' && !in_array(User::userid(), [$this->owner_id, $item->inviter])) { + throw new ApiException('只有群主或邀请人可以移出成员'); + } + if ($item->userid == $this->owner_id) { + throw new ApiException('群主不可' . $typeDesc); + } + if ($item->important) { + throw new ApiException('项目人员或任务人员不可' . $typeDesc); + } + $item->delete(); + } + }); }); - return true; } /** @@ -196,15 +205,19 @@ class WebSocketDialog extends AbstractModel /** * 检查群组类型 + * @param string|array|null $groupType * @return void */ - public function checkGroup($groupType = 'user') + public function checkGroup($groupType = null) { if ($this->type !== 'group') { throw new ApiException('仅限群组操作'); } - if ($this->group_type !== $groupType) { - throw new ApiException('操作的群组类型错误'); + if ($groupType) { + $groupTypes = is_array($groupType) ? $groupType : [$groupType]; + if (!in_array($this->group_type, $groupTypes)) { + throw new ApiException('操作的群组类型错误'); + } } } @@ -260,7 +273,7 @@ class WebSocketDialog extends AbstractModel /** * 获取对话(同时检验对话身份) * @param $dialog_id - * @param bool $checkOwner 是否校验群组身份 + * @param bool|string $checkOwner 是否校验群组身份,'auto'时有群主为true无群主为false * @return self */ public static function checkDialog($dialog_id, $checkOwner = false) @@ -271,11 +284,14 @@ class WebSocketDialog extends AbstractModel } // $userid = User::userid(); + if ($checkOwner === 'auto') { + $checkOwner = $dialog->owner_id > 0; + } if ($checkOwner === true && $dialog->owner_id != $userid) { throw new ApiException('仅限群主操作'); } // - if ($dialog->type === 'group' && $dialog->group_type === 'task') { + if ($dialog->group_type === 'task') { // 任务群对话校验是否在项目内 $project_id = intval(ProjectTask::whereDialogId($dialog->id)->value('project_id')); if ($project_id > 0) { diff --git a/app/Models/WebSocketDialogUser.php b/app/Models/WebSocketDialogUser.php index 54226e057..acf7c1177 100644 --- a/app/Models/WebSocketDialogUser.php +++ b/app/Models/WebSocketDialogUser.php @@ -10,6 +10,8 @@ namespace App\Models; * @property int|null $userid 会员ID * @property string|null $top_at 置顶时间 * @property int|null $mark_unread 是否标记为未读:0否,1是 + * @property int|null $inviter 邀请人 + * @property int|null $important 是否不可移出(项目、任务人员) * @property \Illuminate\Support\Carbon|null $created_at * @property \Illuminate\Support\Carbon|null $updated_at * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser newModelQuery() @@ -18,6 +20,8 @@ namespace App\Models; * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereCreatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereDialogId($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereId($value) + * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereImportant($value) + * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereInviter($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereMarkUnread($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereTopAt($value) * @method static \Illuminate\Database\Eloquent\Builder|WebSocketDialogUser whereUpdatedAt($value) diff --git a/database/migrations/2022_06_22_151032_add_web_socket_dialog_users_inviter_important.php b/database/migrations/2022_06_22_151032_add_web_socket_dialog_users_inviter_important.php new file mode 100644 index 000000000..87d6cb437 --- /dev/null +++ b/database/migrations/2022_06_22_151032_add_web_socket_dialog_users_inviter_important.php @@ -0,0 +1,48 @@ +boolean('important')->default(0)->after('mark_unread')->nullable()->comment('是否不可移出(项目、任务人员)'); + $table->bigInteger('inviter')->nullable()->default(0)->after('mark_unread')->comment('邀请人'); + } + }); + if ($isAdd) { + \App\Models\WebSocketDialog::whereIn('group_type', ['project', 'task'])->chunkById(100, function ($lists) { + /** @var \App\Models\WebSocketDialog $item */ + foreach ($lists as $item) { + \App\Models\WebSocketDialogUser::whereDialogId($item->id)->update([ + 'important' => 1, + ]); + } + }); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('web_socket_dialog_users', function (Blueprint $table) { + $table->dropColumn("important"); + $table->dropColumn("inviter"); + }); + } +} diff --git a/resources/assets/js/pages/manage/components/DialogGroupInfo.vue b/resources/assets/js/pages/manage/components/DialogGroupInfo.vue index fd59ba6a8..45c40457d 100644 --- a/resources/assets/js/pages/manage/components/DialogGroupInfo.vue +++ b/resources/assets/js/pages/manage/components/DialogGroupInfo.vue @@ -19,9 +19,9 @@
-
- - -
-
- +
+ + +
@@ -85,7 +83,7 @@ export default { }, computed: { - ...mapState(['cacheDialogs']), + ...mapState(['cacheDialogs', 'cacheUserBasic']), dialogData() { return this.cacheDialogs.find(({id}) => id == this.dialogId) || {}; @@ -100,8 +98,15 @@ export default { }, userList() { - const {dialogUser, searchKey, dialogData} = this; - const list = dialogUser.filter(item => { + const {dialogUser, searchKey, cacheUserBasic, dialogData} = this; + const list = dialogUser.map(item => { + const userBasic = cacheUserBasic.find(basic => basic.userid == item.userid) + if (userBasic) { + item.nickname = userBasic.nickname + item.email = userBasic.email + } + return item + }).filter(item => { if (searchKey && item.nickname) { if (!$A.strExists(item.nickname, searchKey) && !$A.strExists(item.email, searchKey)) { return false; @@ -171,16 +176,6 @@ export default { }); }, - userResult(user) { - let index = this.dialogUser.findIndex(({userid}) => userid === user.userid); - if (index > -1) { - this.dialogUser.splice(index, 1, Object.assign(user, { - id: this.dialogUser[index].id, - created_at: this.dialogUser[index].created_at - })) - } - }, - openAdd() { this.addData = { dialog_id: this.dialogId, diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index 93679eb07..6a6396e73 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -53,7 +53,6 @@