From 2eee171a5079204764e5031f7369f51e23e1c9b4 Mon Sep 17 00:00:00 2001 From: kuaifan Date: Thu, 4 Jun 2026 13:52:33 +0000 Subject: [PATCH] =?UTF-8?q?feat(project):=20=E7=B3=BB=E7=BB=9F=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E6=96=B0=E5=A2=9E=E3=80=8C=E5=88=9B=E5=BB=BA=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E3=80=8D=E6=9D=83=E9=99=90=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在系统设置「项目相关」新增「创建项目」权限范围(复选): 所有人 / 部门负责人(含部门管理员)/ 指定人员,三者与「所有人」互斥; 系统管理员始终可创建,不受开关限制。未授权用户隐藏「新建项目」入口 (顶部下拉、快捷键、移动端、应用宫格),后端 Project::userCanCreate() 兜底拦截,个人项目(注册自动创建)不受限。 Co-Authored-By: Claude Opus 4.8 --- app/Http/Controllers/Api/SystemController.php | 6 +++ app/Models/Project.php | 36 +++++++++++++++++ app/Models/Setting.php | 8 ++++ language/original-api.txt | 1 + language/original-web.txt | 5 +++ .../setting/components/SystemSetting.vue | 40 +++++++++++++++++++ 6 files changed, 96 insertions(+) diff --git a/app/Http/Controllers/Api/SystemController.php b/app/Http/Controllers/Api/SystemController.php index 177788b60..647f65d1d 100755 --- a/app/Http/Controllers/Api/SystemController.php +++ b/app/Http/Controllers/Api/SystemController.php @@ -69,6 +69,8 @@ class SystemController extends AbstractController 'login_code', 'password_policy', 'project_invite', + 'project_add_permission', + 'project_add_userids', 'chat_information', 'anon_message', 'convert_video', @@ -154,6 +156,10 @@ class SystemController extends AbstractController $setting['department_owner_project_view'] = $setting['department_owner_project_view'] ?: 'close'; $setting['server_timezone'] = config('app.timezone'); $setting['server_version'] = Base::getVersion(); + // 指定人员名单仅管理员可见 + if ($type != 'all' && $type != 'save') { + unset($setting['project_add_userids']); + } // return Base::retSuccess($type == 'save' ? '保存成功' : 'success', $setting ?: json_decode('{}')); } diff --git a/app/Models/Project.php b/app/Models/Project.php index 570783eb7..bfca6a99e 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -605,6 +605,38 @@ class Project extends AbstractModel }); } + /** + * 判断用户是否有权限创建项目(依据系统设置「项目创建权限」) + * @param int $userid + * @return bool + */ + public static function userCanCreate($userid) + { + // 范围已在 Setting::getSettingAttribute() 归一化(默认 ['all']) + $modes = Base::settingFind('system', 'project_add_permission', ['all']); + // 「所有人」:放行(与具体用户无关,避免未携带身份时被误判为无权) + if (in_array('all', $modes)) { + return true; + } + $user = User::find(intval($userid)); + if (empty($user)) { + return false; + } + // 系统管理员始终可创建项目(不受开关限制) + if ($user->isAdmin()) { + return true; + } + // 部门负责人/部门管理员 + if (in_array('departmentOwner', $modes) && UserDepartment::getManagedDepartments($user->userid)->isNotEmpty()) { + return true; + } + // 指定人员 + if (in_array('appoint', $modes)) { + return in_array($user->userid, Base::settingFind('system', 'project_add_userids', [])); + } + return false; + } + /** * 创建项目 * @param $params @@ -621,6 +653,10 @@ class Project extends AbstractModel $desc = trim(Arr::get($params, 'desc', '')); $flow = trim(Arr::get($params, 'flow', 'close')); $isPersonal = intval(Arr::get($params, 'personal')); + // 个人项目为系统自动创建,不受创建权限限制 + if (!$isPersonal && !self::userCanCreate($userid)) { + return Base::retError('当前仅指定人员可以创建项目'); + } if (mb_strlen($name) < 2) { return Base::retError('项目名称不可以少于2个字'); } elseif (mb_strlen($name) > 32) { diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 658751fa5..1bbfddebe 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -59,6 +59,14 @@ class Setting extends AbstractModel if (!is_array($value['task_default_time']) || count($value['task_default_time']) != 2 || !Timer::isTime($value['task_default_time'][0]) || !Timer::isTime($value['task_default_time'][1])) { $value['task_default_time'] = ['09:00', '18:00']; } + // 项目创建权限:范围(all/departmentOwner/appoint,默认 all)+ 指定人员 + $value['project_add_permission'] = array_values(array_intersect( + is_array($value['project_add_permission'] ?? null) ? $value['project_add_permission'] : [], + ['all', 'departmentOwner', 'appoint'] + )) ?: ['all']; + $value['project_add_userids'] = is_array($value['project_add_userids'] ?? null) + ? array_values(array_unique(array_filter(array_map('intval', $value['project_add_userids'])))) + : []; break; // 文件设置 diff --git a/language/original-api.txt b/language/original-api.txt index 7a6d88e92..0ddd1f67e 100644 --- a/language/original-api.txt +++ b/language/original-api.txt @@ -995,3 +995,4 @@ LDAP 用户缺少邮箱属性,请联系管理员配置 发送者昵称最多不能超过20字 AI 助手 没有查看权限 +当前仅指定人员可以创建项目 diff --git a/language/original-web.txt b/language/original-web.txt index cf770d82d..55daedf4d 100644 --- a/language/original-web.txt +++ b/language/original-web.txt @@ -2449,3 +2449,8 @@ AI任务分析 (*)分钟前 (*)小时前 (*)天前 +所有人:所有成员均可创建项目。 +可创建项目的人员 +系统管理员(始终可创建,不受开关限制)。 +部门负责人与部门管理员。 +下方指定的人员。 diff --git a/resources/assets/js/pages/manage/setting/components/SystemSetting.vue b/resources/assets/js/pages/manage/setting/components/SystemSetting.vue index e56b5410c..14ed5776a 100644 --- a/resources/assets/js/pages/manage/setting/components/SystemSetting.vue +++ b/resources/assets/js/pages/manage/setting/components/SystemSetting.vue @@ -75,6 +75,26 @@
{{$L('开启:项目管理员可生成链接邀请成员加入项目。')}}
+ + + {{$L('所有人')}} + {{$L('部门负责人')}} + {{$L('指定人员')}} + +
{{$L('所有人:所有成员均可创建项目。')}}
+
+

{{$L('可创建项目的人员')}}:

+
    +
  1. {{$L('系统管理员(始终可创建,不受开关限制)。')}}
  2. +
  3. {{$L('部门负责人与部门管理员。')}}
  4. +
  5. {{$L('下方指定的人员。')}}
  6. +
+
+ +
{{$L('开启')}} @@ -316,10 +336,13 @@