From e7874661f34329da234c5226442c0a9a000d587e Mon Sep 17 00:00:00 2001 From: kuaifan Date: Mon, 14 Jun 2021 17:44:46 +0800 Subject: [PATCH] no message --- .../Controllers/Api/ProjectController.php | 37 +++------ app/Models/Project.php | 78 ++++++++++++++----- app/Models/ProjectColumn.php | 9 ++- app/Models/ProjectTask.php | 53 ++++++++++++- app/Models/ProjectUser.php | 17 ---- app/Models/WebSocketDialog.php | 2 +- resources/assets/js/pages/manage.vue | 2 +- .../pages/manage/components/ProjectList.vue | 4 +- .../assets/js/pages/manage/messenger.vue | 5 +- resources/assets/js/store/actions.js | 33 ++++---- .../statics/public/js/scroll-into-view.min.js | 1 + 11 files changed, 153 insertions(+), 88 deletions(-) create mode 100644 resources/assets/statics/public/js/scroll-into-view.min.js diff --git a/app/Http/Controllers/Api/ProjectController.php b/app/Http/Controllers/Api/ProjectController.php index a54f53c4..4abdd4c4 100755 --- a/app/Http/Controllers/Api/ProjectController.php +++ b/app/Http/Controllers/Api/ProjectController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers\Api; use App\Models\AbstractModel; use App\Models\Project; use App\Models\ProjectColumn; -use App\Models\ProjectLog; use App\Models\ProjectTask; use App\Models\ProjectTaskFile; use App\Models\ProjectUser; @@ -177,11 +176,6 @@ class ProjectController extends AbstractController 'userid' => $project->userid, 'owner' => 1, ])->save(); - ProjectLog::createInstance([ - 'project_id' => $project->id, - 'userid' => $project->userid, - 'detail' => '创建项目', - ])->save(); foreach ($insertColumns AS $column) { $column['project_id'] = $project->id; ProjectColumn::createInstance($column)->save(); @@ -332,17 +326,13 @@ class ProjectController extends AbstractController // return AbstractModel::transaction(function() use ($project, $userid) { $array = []; - foreach ($userid as $value) { - if ($value > 0 && $project->joinProject($value)) { - $array[] = $value; - } - } - $delUser = ProjectUser::whereProjectId($project->id)->whereNotIn('userid', $array)->get(); - if ($delUser->isNotEmpty()) { - foreach ($delUser as $value) { - $value->exitProject(); + foreach ($userid as $uid) { + if ($project->joinProject($uid)) { + $array[] = $uid; } } + ProjectUser::whereProjectId($project->id)->whereNotIn('userid', $array)->delete(); + $project->syncDialogUser(); return Base::retSuccess('修改成功'); }); } @@ -389,6 +379,7 @@ class ProjectController extends AbstractController ], [ 'owner' => 1, ]); + $project->syncDialogUser(); // return Base::retSuccess('移交成功'); }); @@ -423,11 +414,11 @@ class ProjectController extends AbstractController return Base::retError('项目负责人无法退出项目'); } // - $projectUser = ProjectUser::whereProjectId($project->id)->whereUserid($user->userid)->first(); - if ($projectUser->exitProject()) { + return AbstractModel::transaction(function() use ($user, $project) { + ProjectUser::whereProjectId($project->id)->whereUserid($user->userid)->delete(); + $project->syncDialogUser(); return Base::retSuccess('退出成功'); - } - return Base::retError('退出失败'); + }); } /** @@ -1011,13 +1002,7 @@ class ProjectController extends AbstractController return AbstractModel::transaction(function() use ($task) { if (empty($task->dialog_id)) { $task->lockForUpdate(); - $userids = $task->taskUser->pluck('userid')->toArray(); - $items = ProjectTask::with(['taskUser'])->where('parent_id', $task->id)->whereNull('archived_at')->get(); - foreach ($items as $item) { - $userids = array_merge($userids, $item->taskUser->pluck('userid')->toArray()); - } - $userids = array_values(array_filter(array_unique($userids))); - $dialog = WebSocketDialog::createGroup('', $userids, 'task'); + $dialog = WebSocketDialog::createGroup(null, $task->relationUserids(), 'task'); if ($dialog) { $task->dialog_id = $dialog->id; $task->save(); diff --git a/app/Models/Project.php b/app/Models/Project.php index 286bac86..3d724ddb 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -143,11 +143,17 @@ class Project extends AbstractModel public function getDialogIdAttribute($value) { if ($value === 0) { - $userid = $this->projectUser->pluck('userid')->toArray(); - $dialog = WebSocketDialog::createGroup('', $userid, 'project'); - if ($dialog) { - $this->dialog_id = $value = $dialog->id; - $this->save(); + $result = AbstractModel::transaction(function() { + $this->lockForUpdate(); + $dialog = WebSocketDialog::createGroup(null, $this->relationUserids(), 'project'); + if ($dialog) { + $this->dialog_id = $dialog->id; + $this->save(); + } + return Base::retSuccess('success', $dialog->id); + }); + if (Base::isSuccess($result)) { + $value = $result['data']; } } return $value; @@ -182,18 +188,48 @@ class Project extends AbstractModel * @param int $userid 加入的会员ID * @return bool */ - public function joinProject($userid) { - $result = AbstractModel::transaction(function () use ($userid) { - ProjectUser::updateInsert([ - 'project_id' => $this->id, - 'userid' => $userid, - ]); - WebSocketDialogUser::updateInsert([ - 'dialog_id' => $this->dialog_id, - 'userid' => $userid, - ]); + public function joinProject($userid) + { + if (empty($userid)) { + return false; + } + if (!User::whereUserid($userid)->exists()) { + return false; + } + ProjectUser::updateInsert([ + 'project_id' => $this->id, + 'userid' => $userid, + ]); + return true; + } + + /** + * 同步项目成员至聊天室 + */ + public function syncDialogUser() + { + if (empty($this->dialog_id)) { + return; + } + AbstractModel::transaction(function() { + $userids = $this->relationUserids(); + foreach ($userids as $userid) { + WebSocketDialogUser::updateInsert([ + 'dialog_id' => $this->dialog_id, + 'userid' => $userid, + ]); + } + WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->delete(); }); - return Base::isSuccess($result); + } + + /** + * 获取相关所有人员(项目负责人、项目成员) + * @return array + */ + public function relationUserids() + { + return $this->projectUser->pluck('userid')->toArray(); } /** @@ -203,13 +239,15 @@ class Project extends AbstractModel public function deleteProject() { $result = AbstractModel::transaction(function () { - ProjectTask::whereProjectId($this->id)->delete(); - ProjectColumn::whereProjectId($this->id)->delete(); WebSocketDialog::whereId($this->dialog_id)->delete(); + $columns = ProjectColumn::whereProjectId($this->id)->get(); + foreach ($columns as $column) { + $column->deleteColumn(); + } if ($this->delete()) { - return Base::retSuccess('success'); + return Base::retSuccess('删除成功', $this->toArray()); } else { - return Base::retError('error'); + return Base::retError('删除失败', $this->toArray()); } }); return Base::isSuccess($result); diff --git a/app/Models/ProjectColumn.php b/app/Models/ProjectColumn.php index 2d240993..a51c9790 100644 --- a/app/Models/ProjectColumn.php +++ b/app/Models/ProjectColumn.php @@ -54,11 +54,14 @@ class ProjectColumn extends AbstractModel public function deleteColumn() { $result = AbstractModel::transaction(function () { - ProjectTask::whereColumnId($this->id)->delete(); + $tasks = ProjectTask::whereColumnId($this->id)->get(); + foreach ($tasks as $task) { + $task->deleteTask(); + } if ($this->delete()) { - return Base::retSuccess('success'); + return Base::retSuccess('删除成功', $this->toArray()); } else { - return Base::retError('error'); + return Base::retError('删除失败', $this->toArray()); } }); return Base::isSuccess($result); diff --git a/app/Models/ProjectTask.php b/app/Models/ProjectTask.php index 4c766f54..9052a323 100644 --- a/app/Models/ProjectTask.php +++ b/app/Models/ProjectTask.php @@ -367,6 +367,7 @@ class ProjectTask extends AbstractModel ], [ 'owner' => 1, ]); + $this->syncDialogUser(); } } // 计划时间 @@ -403,6 +404,7 @@ class ProjectTask extends AbstractModel $array[] = $uid; } ProjectTaskUser::whereTaskId($this->id)->where('owner', '!=', 1)->whereNotIn('userid', $array)->delete(); + $this->syncDialogUser(); } // 背景色 if (Arr::exists($data, 'color')) { @@ -436,6 +438,47 @@ class ProjectTask extends AbstractModel }); } + /** + * 同步项目成员至聊天室 + */ + public function syncDialogUser() + { + if ($this->parent_id > 0) { + $task = self::find($this->parent_id); + if ($task) { + $task->syncDialogUser(); + } + return; + } + if (empty($this->dialog_id)) { + return; + } + AbstractModel::transaction(function() { + $userids = $this->relationUserids(); + foreach ($userids as $userid) { + WebSocketDialogUser::updateInsert([ + 'dialog_id' => $this->dialog_id, + 'userid' => $userid, + ]); + } + WebSocketDialogUser::whereDialogId($this->dialog_id)->whereNotIn('userid', $userids)->delete(); + }); + } + + /** + * 获取任务所有人员(负责人、协助人员、子任务负责人) + * @return array + */ + public function relationUserids() + { + $userids = $this->taskUser->pluck('userid')->toArray(); + $items = ProjectTask::with(['taskUser'])->where('parent_id', $this->id)->whereNull('archived_at')->get(); + foreach ($items as $item) { + $userids = array_merge($userids, $item->taskUser->pluck('userid')->toArray()); + } + return array_values(array_filter(array_unique($userids))); + } + /** * 标记已完成、未完成 * @param Carbon|null $complete_at 完成时间 @@ -488,8 +531,14 @@ class ProjectTask extends AbstractModel public function deleteTask() { return AbstractModel::transaction(function () { - $this->delete(); - return Base::retSuccess('删除成功', $this->toArray()); + if ($this->dialog_id) { + WebSocketDialog::whereId($this->dialog_id)->delete(); + } + if ($this->delete()) { + return Base::retSuccess('删除成功', $this->toArray()); + } else { + return Base::retError('删除失败', $this->toArray()); + } }); } } diff --git a/app/Models/ProjectUser.php b/app/Models/ProjectUser.php index fd7d1536..1bc0d966 100644 --- a/app/Models/ProjectUser.php +++ b/app/Models/ProjectUser.php @@ -36,21 +36,4 @@ class ProjectUser extends AbstractModel { return $this->hasOne(Project::class, 'id', 'project_id'); } - - /** - * 退出项目 - * @return bool - */ - public function exitProject() { - $result = AbstractModel::transaction(function () { - WebSocketDialogUser::whereDialogId($this->project->dialog_id)->whereUserid($this->userid)->delete(); - if ($this->delete()) { - return Base::retSuccess('success'); - } else { - return Base::retError('error'); - } - }); - return Base::isSuccess($result); - } - } diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index 01abb7ec..aea99089 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -84,7 +84,7 @@ class WebSocketDialog extends AbstractModel $result = AbstractModel::transaction(function () use ($userid, $group_type, $name) { $dialog = self::createInstance([ 'type' => 'group', - 'name' => $name, + 'name' => $name ?: '', 'group_type' => $group_type, ]); $dialog->save(); diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index 7803c6e7..1a8d4b1d 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -222,7 +222,7 @@ export default { classNameRoute(path, openMenu) { return { - "active": $A.leftExists(this.curPath, '/manage/' + path), + "active": this.curPath == '/manage/' + path, "open-menu": openMenu === true, }; }, diff --git a/resources/assets/js/pages/manage/components/ProjectList.vue b/resources/assets/js/pages/manage/components/ProjectList.vue index 8502ab71..43fc4b1f 100644 --- a/resources/assets/js/pages/manage/components/ProjectList.vue +++ b/resources/assets/js/pages/manage/components/ProjectList.vue @@ -253,7 +253,7 @@ -
+
@@ -268,7 +268,7 @@
-
+
diff --git a/resources/assets/js/pages/manage/messenger.vue b/resources/assets/js/pages/manage/messenger.vue index 89d01d81..7f8e0353 100644 --- a/resources/assets/js/pages/manage/messenger.vue +++ b/resources/assets/js/pages/manage/messenger.vue @@ -137,9 +137,10 @@ export default { }, openContacts(user) { - this.$store.dispatch("openDialogUserid", user.userid); this.tabActive = 'dialog'; - this.scrollIntoActive(); + this.$store.dispatch("openDialogUserid", user.userid).then(() => { + this.scrollIntoActive() + }); }, getContactsList() { diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index 0ff7da80..13e318c0 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -750,20 +750,25 @@ export default { * @param userid */ openDialogUserid({state, dispatch}, userid) { - if (userid === state.userId) { - return; - } - dispatch("call", { - url: 'dialog/open/user', - data: { - userid, - }, - }).then(result => { - state.method.setStorage("messengerDialogId", result.data.id) - dispatch("getDialogMsgList", result.data.id); - dispatch("saveDialog", result.data); - }).catch(result => { - $A.modalError(result.msg); + return new Promise(function (resolve, reject) { + if (userid === state.userId) { + reject(); + return; + } + dispatch("call", { + url: 'dialog/open/user', + data: { + userid, + }, + }).then(result => { + state.method.setStorage("messengerDialogId", result.data.id) + dispatch("getDialogMsgList", result.data.id); + dispatch("saveDialog", result.data); + resolve(result); + }).catch(result => { + $A.modalError(result.msg); + reject(result); + }); }); }, diff --git a/resources/assets/statics/public/js/scroll-into-view.min.js b/resources/assets/statics/public/js/scroll-into-view.min.js new file mode 100644 index 00000000..b01f390f --- /dev/null +++ b/resources/assets/statics/public/js/scroll-into-view.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).scrollIntoView=t()}(this,(function(){"use strict";function e(e){return"object"==typeof e&&null!=e&&1===e.nodeType}function t(e,t){return(!t||"hidden"!==e)&&"visible"!==e&&"clip"!==e}function n(e,n){if(e.clientHeightt||i>e&&l=t&&u>=n?i-e-o:l>t&&un?l-t+r:0}function r(t,r){var i=window,l=r.scrollMode,u=r.block,c=r.inline,f=r.boundary,d=r.skipOverflowHiddenElements,a="function"==typeof f?f:function(e){return e!==f};if(!e(t))throw new TypeError("Invalid target");for(var s=document.scrollingElement||document.documentElement,h=[],p=t;e(p)&&a(p);){if((p=p.parentElement)===s){h.push(p);break}null!=p&&p===document.body&&n(p)&&!n(document.documentElement)||null!=p&&n(p,d)&&h.push(p)}for(var m=i.visualViewport?i.visualViewport.width:innerWidth,g=i.visualViewport?i.visualViewport.height:innerHeight,v=window.scrollX||pageXOffset,w=window.scrollY||pageYOffset,b=t.getBoundingClientRect(),y=b.height,W=b.width,H=b.top,E=b.right,M=b.bottom,T=b.left,V="start"===u||"nearest"===u?H:"end"===u?M:H+y/2,k="center"===c?T+W/2:"end"===c?E:T,x=[],I=0;I=0&&T>=0&&M<=g&&E<=m&&H>=D&&M<=R&&T>=X&&E<=L)return x;var Y=getComputedStyle(O),S=parseInt(Y.borderLeftWidth,10),q=parseInt(Y.borderTopWidth,10),z=parseInt(Y.borderRightWidth,10),A=parseInt(Y.borderBottomWidth,10),F=0,G=0,J="offsetWidth"in O?O.offsetWidth-O.clientWidth-S-z:0,K="offsetHeight"in O?O.offsetHeight-O.clientHeight-q-A:0;if(s===O)F="start"===u?V:"end"===u?V-g:"nearest"===u?o(w,w+g,g,q,A,w+V,w+V+y,y):V-g/2,G="start"===c?k:"center"===c?k-m/2:"end"===c?k-m:o(v,v+m,m,S,z,v+k,v+k+W,W),F=Math.max(0,F+w),G=Math.max(0,G+v);else{F="start"===u?V-D-q:"end"===u?V-R+A+K:"nearest"===u?o(D,R,B,q,A+K,V,V+y,y):V-(D+B/2)+K/2,G="start"===c?k-X-S:"center"===c?k-(X+C/2)+J/2:"end"===c?k-L+z+J:o(X,L,C,S,z+J,k,k+W,W);var N=O.scrollLeft,P=O.scrollTop;V+=P-(F=Math.max(0,Math.min(P+F,O.scrollHeight-B+K))),k+=N-(G=Math.max(0,Math.min(N+G,O.scrollWidth-C+J)))}x.push({el:O,top:F,left:G})}return x}function i(e){return e===Object(e)&&0!==Object.keys(e).length}return function(e,t){var n=!e.ownerDocument.documentElement.contains(e);if(i(t)&&"function"==typeof t.behavior)return t.behavior(n?[]:r(e,t));if(!n){var o=function(e){return!1===e?{block:"end",inline:"nearest"}:i(e)?e:{block:"start",inline:"nearest"}}(t);return function(e,t){void 0===t&&(t="auto");var n="scrollBehavior"in document.body.style;e.forEach((function(e){var o=e.el,r=e.top,i=e.left;o.scroll&&n?o.scroll({top:r,left:i,behavior:t}):(o.scrollTop=r,o.scrollLeft=i)}))}(r(e,o),o.behavior)}}}));