no message

This commit is contained in:
kuaifan 2021-06-14 17:44:46 +08:00
parent 27308cdebc
commit e7874661f3
11 changed files with 153 additions and 88 deletions

View File

@ -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();

View File

@ -143,12 +143,18 @@ class Project extends AbstractModel
public function getDialogIdAttribute($value)
{
if ($value === 0) {
$userid = $this->projectUser->pluck('userid')->toArray();
$dialog = WebSocketDialog::createGroup('', $userid, 'project');
$result = AbstractModel::transaction(function() {
$this->lockForUpdate();
$dialog = WebSocketDialog::createGroup(null, $this->relationUserids(), 'project');
if ($dialog) {
$this->dialog_id = $value = $dialog->id;
$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) {
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);

View File

@ -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);

View File

@ -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();
if ($this->dialog_id) {
WebSocketDialog::whereId($this->dialog_id)->delete();
}
if ($this->delete()) {
return Base::retSuccess('删除成功', $this->toArray());
} else {
return Base::retError('删除失败', $this->toArray());
}
});
}
}

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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,
};
},

View File

@ -253,7 +253,7 @@
</div>
</div>
<!--未完成任务-->
<div :class="['project-table-body', !taskUndoneShow ? 'project-table-hide' : '']">
<div v-if="projectDetail.task_num > 0" :class="['project-table-body', !taskUndoneShow ? 'project-table-hide' : '']">
<Row class="task-row">
<Col span="12" class="row-title">
<i class="iconfont" @click="toggleBoolean('taskUndoneShow')">&#xe689;</i>
@ -268,7 +268,7 @@
<TaskRow :list="undoneList" :color-list="taskColorList" @command="dropTask"/>
</div>
<!--已完成任务-->
<div :class="['project-table-body', !taskCompletedShow ? 'project-table-hide' : '']">
<div v-if="projectDetail.task_num > 0" :class="['project-table-body', !taskCompletedShow ? 'project-table-hide' : '']">
<Row class="task-row">
<Col span="12" class="row-title">
<i class="iconfont" @click="toggleBoolean('taskCompletedShow')">&#xe689;</i>

View File

@ -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() {

View File

@ -750,7 +750,9 @@ export default {
* @param userid
*/
openDialogUserid({state, dispatch}, userid) {
return new Promise(function (resolve, reject) {
if (userid === state.userId) {
reject();
return;
}
dispatch("call", {
@ -762,8 +764,11 @@ export default {
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);
});
});
},

View File

@ -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.clientHeight<e.scrollHeight||e.clientWidth<e.scrollWidth){var o=getComputedStyle(e,null);return t(o.overflowY,n)||t(o.overflowX,n)||function(e){var t=function(e){if(!e.ownerDocument||!e.ownerDocument.defaultView)return null;try{return e.ownerDocument.defaultView.frameElement}catch(e){return null}}(e);return!!t&&(t.clientHeight<e.scrollHeight||t.clientWidth<e.scrollWidth)}(e)}return!1}function o(e,t,n,o,r,i,l,u){return i<e&&l>t||i>e&&l<t?0:i<=e&&u<=n||l>=t&&u>=n?i-e-o:l>t&&u<n||i<e&&u>n?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<h.length;I++){var O=h[I],j=O.getBoundingClientRect(),B=j.height,C=j.width,D=j.top,L=j.right,R=j.bottom,X=j.left;if("if-needed"===l&&H>=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)}}}));