diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index b99386e1b..b9dc866f2 100755 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -502,6 +502,7 @@ class UsersController extends AbstractController * - yes: 已认证 * - no: 未认证 * - 其他值: 全部(默认) + * - keys.department 部门ID(0表示默认部门,不赋值获取所有部门) * * @apiParam {Number} [page] 当前页,默认:1 * @apiParam {Number} [pagesize] 每页显示数量,默认:20,最大:50 @@ -560,6 +561,15 @@ class UsersController extends AbstractController } elseif ($keys['email_verity'] === 'no') { $builder->whereEmailVerity(0); } + if (isset($keys['department'])) { + if ($keys['department'] == '0') { + $builder->where(function($query) { + $query->where("department", "")->orWhere("department", ",,"); + }); + } else { + $builder->where("department", "like", "%,{$keys['department']},%"); + } + } } else { $builder->whereNull('disable_at'); } @@ -580,6 +590,7 @@ class UsersController extends AbstractController * @apiParam {String} [type] 操作 * - setadmin 设为管理员 * - clearadmin 取消管理员 + * - department 修改部门(需要参数 department) * - setdisable 设为离职(需要参数 disable_time、transfer_userid) * - cleardisable 取消离职 * - delete 删除会员(需要参数 delete_reason) @@ -588,6 +599,7 @@ class UsersController extends AbstractController * @apiParam {String} [password] 新的密码 * @apiParam {String} [nickname] 昵称 * @apiParam {String} [profession] 职位 + * @apiParam {String} [department] 部门 * @apiParam {String} [disable_time] 离职时间 * @apiParam {String} [transfer_userid] 离职交接人 * @apiParam {String} [delete_reason] 删除原因 @@ -622,6 +634,18 @@ class UsersController extends AbstractController $upArray['identity'] = array_diff($userInfo->identity, ['admin']); break; + case 'department': + if (!is_array($data['department'])) { + $data['department'] = []; + } + foreach ($data['department'] as $id) { + if (!UserDepartment::whereId($id)->exists()) { + return Base::retError('修改部门不存在'); + } + } + $upArray['department'] = $data['department']; + break; + case 'setdisable': if ($userInfo->userid === $user->userid) { return Base::retError('不能操作自己离职'); @@ -660,6 +684,9 @@ class UsersController extends AbstractController if (isset($upArray['identity'])) { $upArray['identity'] = "," . implode(",", $upArray['identity']) . ","; } + if (isset($upArray['department'])) { + $upArray['department'] = "," . implode(",", $upArray['department']) . ","; + } // 邮箱 if (Arr::exists($data, 'email')) { $email = trim($data['email']); @@ -710,9 +737,29 @@ class UsersController extends AbstractController } if ($upArray) { AbstractModel::transaction(function() use ($user, $type, $upArray, $userInfo, $transferUser) { + $exitIds = array_diff($userInfo->department, Base::explodeInt($upArray['department'])); + $joinIds = array_diff(Base::explodeInt($upArray['department']), $userInfo->department); $userInfo->updateInstance($upArray); $userInfo->save(); - if ($type === 'setdisable') { + if ($type === 'department') { + $userids = [$userInfo->userid]; + // 退出群组 + $exitDepartments = UserDepartment::whereIn('id', $exitIds)->get(); + foreach ($exitDepartments as $exitDepartment) { + if ($exitDepartment->dialog_id > 0 && $exitDialog = WebSocketDialog::find($exitDepartment->dialog_id)) { + $exitDialog->exitGroup($userids, 'remove', false); + $exitDialog->pushMsg("groupExit", null, $userids); + } + } + // 加入群组 + $joinDepartments = UserDepartment::whereIn('id', $joinIds)->get(); + foreach ($joinDepartments as $joinDepartment) { + if ($joinDepartment->dialog_id > 0 && $joinDialog = WebSocketDialog::find($joinDepartment->dialog_id)) { + $joinDialog->joinGroup($userids, 0, true); + $joinDialog->pushMsg("groupJoin", null, $userids); + } + } + } elseif ($type === 'setdisable') { $userTransfer = UserTransfer::createInstance([ 'original_userid' => $userInfo->userid, 'new_userid' => $transferUser->userid, @@ -1193,12 +1240,11 @@ class UsersController extends AbstractController return Base::retError('请选择正确的部门负责人'); } // - $userDepartment->updateInstance([ + $userDepartment->saveDepartment([ 'name' => $name, 'parent_id' => $parent_id, 'owner_userid' => $owner_userid, ]); - $userDepartment->saveDepartment(); // return Base::retSuccess($parent_id > 0 ? '保存成功' : '新建成功'); } diff --git a/app/Models/User.php b/app/Models/User.php index 5c5ad7c9d..14c276781 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -13,6 +13,7 @@ use Carbon\Carbon; * * @property int $userid * @property array $identity 身份 + * @property array $department 所属部门 * @property string|null $az A-Z * @property string|null $pinyin 拼音(主要用于搜索) * @property string|null $email 邮箱 @@ -42,6 +43,7 @@ use Carbon\Carbon; * @method static \Illuminate\Database\Eloquent\Builder|User whereChangepass($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedAt($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereCreatedIp($value) + * @method static \Illuminate\Database\Eloquent\Builder|User whereDepartment($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereDisableAt($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereEmail($value) * @method static \Illuminate\Database\Eloquent\Builder|User whereEmailVerity($value) @@ -133,6 +135,19 @@ class User extends AbstractModel return array_filter(is_array($value) ? $value : explode(",", trim($value, ","))); } + /** + * 部门 + * @param $value + * @return array + */ + public function getDepartmentAttribute($value) + { + if (empty($value)) { + return []; + } + return array_filter(is_array($value) ? $value : explode(",", trim($value, ","))); + } + /** * 是否在线 * @return bool diff --git a/app/Models/UserDepartment.php b/app/Models/UserDepartment.php index 3c7cfa4bf..a1f485445 100644 --- a/app/Models/UserDepartment.php +++ b/app/Models/UserDepartment.php @@ -2,6 +2,8 @@ namespace App\Models; +use App\Exceptions\ApiException; + /** * App\Models\UserDepartment * @@ -26,14 +28,48 @@ namespace App\Models; */ class UserDepartment extends AbstractModel { - /** * 保存部门 - * @return bool + * @param $data */ - public function saveDepartment() { - // todo 聊天室相关 - return $this->save(); + public function saveDepartment($data = []) { + AbstractModel::transaction(function () use ($data) { + $oldUser = null; + $newUser = null; + if ($data['owner_userid'] !== $this->owner_userid) { + $oldUser = User::find($this->owner_userid); + $newUser = User::find($data['owner_userid']); + } + $this->updateInstance($data); + // + if ($this->dialog_id > 0) { + $dialog = WebSocketDialog::find($this->dialog_id); + if ($dialog) { + $dialog->name = $this->name; + $dialog->owner_id = $this->owner_userid; + $dialog->save(); + } + } else { + $dialog = WebSocketDialog::createGroup($this->name, [$this->owner_userid], 'department', $this->owner_userid); + if (empty($dialog)) { + throw new ApiException("创建群组失败"); + } + $this->dialog_id = $dialog->id; + } + $this->save(); + // + if ($oldUser) { + $oldUser->department = array_diff($oldUser->department, [$this->id]); + $oldUser->department = "," . implode(",", $oldUser->department) . ","; + $oldUser->save(); + } + if ($newUser) { + $newUser->department = array_diff($newUser->department, [$this->id]); + $newUser->department = array_merge($newUser->department, [$this->id]); + $newUser->department = "," . implode(",", $newUser->department) . ","; + $newUser->save(); + } + }); } /** @@ -41,11 +77,27 @@ class UserDepartment extends AbstractModel * @return void */ public function deleteDepartment() { + // 删除子部门 $list = self::whereParentId($this->id)->get(); foreach ($list as $item) { $item->deleteDepartment(); } - // todo 移动成员 + // 移出成员 + User::where("department", "like", "%,{$this->id},%")->chunk(100, function($items) { + /** @var User $user */ + foreach ($items as $user) { + $user->department = array_diff($user->department, [$this->id]); + $user->department = "," . implode(",", $user->department) . ","; + $user->save(); + } + }); + // 解散群组 + $dialog = WebSocketDialog::find($this->dialog_id); + if ($dialog) { + $dialog->deleteDialog(); + $dialog->pushMsg("groupDelete"); + } + // $this->delete(); } } diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index 52a87cbd0..2de6044dc 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -144,11 +144,12 @@ class WebSocketDialog extends AbstractModel * 加入聊天室 * @param int|array $userid 加入的会员ID或会员ID组 * @param int $inviter 邀请人 + * @param bool $important 重要人员 * @return bool */ - public function joinGroup($userid, $inviter) + public function joinGroup($userid, $inviter, $important = false) { - AbstractModel::transaction(function () use ($inviter, $userid) { + AbstractModel::transaction(function () use ($important, $inviter, $userid) { foreach (is_array($userid) ? $userid : [$userid] as $value) { if ($value > 0) { WebSocketDialogUser::updateInsert([ @@ -156,6 +157,7 @@ class WebSocketDialog extends AbstractModel 'userid' => $value, ], [ 'inviter' => $inviter, + 'important' => $important ? 1 : 0, ]); WebSocketDialogMsg::sendMsg(null, $this->id, 'notice', [ 'notice' => User::userid2nickname($value) . " 已加入群组" @@ -198,7 +200,7 @@ class WebSocketDialog extends AbstractModel throw new ApiException('群主不可' . $typeDesc); } if ($item->important) { - throw new ApiException('项目人员或任务人员不可' . $typeDesc); + throw new ApiException('部门成员、项目人员或任务人员不可' . $typeDesc); } } // @@ -396,7 +398,7 @@ class WebSocketDialog extends AbstractModel 'name' => $name ?: '', 'group_type' => $group_type, 'owner_id' => $owner_id, - 'last_at' => in_array($group_type, ['user', 'all']) ? Carbon::now() : null, + 'last_at' => in_array($group_type, ['user', 'department', 'all']) ? Carbon::now() : null, ]); $dialog->save(); foreach (is_array($userid) ? $userid : [$userid] as $value) { diff --git a/app/Models/WebSocketDialogUser.php b/app/Models/WebSocketDialogUser.php index acf7c1177..1f48cf039 100644 --- a/app/Models/WebSocketDialogUser.php +++ b/app/Models/WebSocketDialogUser.php @@ -11,7 +11,7 @@ namespace App\Models; * @property string|null $top_at 置顶时间 * @property int|null $mark_unread 是否标记为未读:0否,1是 * @property int|null $inviter 邀请人 - * @property int|null $important 是否不可移出(项目、任务人员) + * @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() diff --git a/database/migrations/2022_11_17_103811_add_users_department.php b/database/migrations/2022_11_17_103811_add_users_department.php new file mode 100644 index 000000000..7b26cb125 --- /dev/null +++ b/database/migrations/2022_11_17_103811_add_users_department.php @@ -0,0 +1,34 @@ +string('department', 255)->nullable()->default('')->after('identity')->comment('所属部门'); + } + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn("department"); + }); + } +} diff --git a/resources/assets/js/pages/manage/components/DialogGroupInfo.vue b/resources/assets/js/pages/manage/components/DialogGroupInfo.vue index 2ca5e9763..910fa56ec 100644 --- a/resources/assets/js/pages/manage/components/DialogGroupInfo.vue +++ b/resources/assets/js/pages/manage/components/DialogGroupInfo.vue @@ -34,7 +34,9 @@
- +
@@ -45,7 +47,10 @@ :mask-closable="false">
- + +
{{$L('此操作仅加入群成员并不会加入部门')}}
+
{{$L('此操作仅加入群成员并不会加入项目')}}
+
{{$L('此操作仅加入群成员并不会加入任务负责人')}}
@@ -95,6 +100,7 @@ export default { groupType() { const {group_type} = this.dialogData + if (group_type === 'department') return '部门群组' if (group_type === 'project') return '项目群组' if (group_type === 'task') return '任务群组' if (group_type === 'user') return '个人群组' diff --git a/resources/assets/js/pages/manage/components/DialogWrapper.vue b/resources/assets/js/pages/manage/components/DialogWrapper.vue index e86c6e577..a7d2d275e 100644 --- a/resources/assets/js/pages/manage/components/DialogWrapper.vue +++ b/resources/assets/js/pages/manage/components/DialogWrapper.vue @@ -20,7 +20,8 @@
@@ -40,6 +41,8 @@

{{dialogData.name}}

({{peopleNum}}) + {{$L('全员')}} + {{$L('部门')}}