mirror of
https://github.com/kuaifan/dootask.git
synced 2026-07-27 16:37:52 +00:00
feat(project): 系统设置新增「创建项目」权限开关
在系统设置「项目相关」新增「创建项目」权限范围(复选): 所有人 / 部门负责人(含部门管理员)/ 指定人员,三者与「所有人」互斥; 系统管理员始终可创建,不受开关限制。未授权用户隐藏「新建项目」入口 (顶部下拉、快捷键、移动端、应用宫格),后端 Project::userCanCreate() 兜底拦截,个人项目(注册自动创建)不受限。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
fd6a8a3650
commit
2eee171a50
@ -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('{}'));
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
// 文件设置
|
||||
|
||||
@ -995,3 +995,4 @@ LDAP 用户缺少邮箱属性,请联系管理员配置
|
||||
发送者昵称最多不能超过20字
|
||||
AI 助手
|
||||
没有查看权限
|
||||
当前仅指定人员可以创建项目
|
||||
|
||||
@ -2449,3 +2449,8 @@ AI任务分析
|
||||
(*)分钟前
|
||||
(*)小时前
|
||||
(*)天前
|
||||
所有人:所有成员均可创建项目。
|
||||
可创建项目的人员
|
||||
系统管理员(始终可创建,不受开关限制)。
|
||||
部门负责人与部门管理员。
|
||||
下方指定的人员。
|
||||
|
||||
@ -75,6 +75,26 @@
|
||||
</RadioGroup>
|
||||
<div v-if="formDatum.project_invite == 'open'" class="form-tip">{{$L('开启:项目管理员可生成链接邀请成员加入项目。')}}</div>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('创建项目')" prop="project_add_permission">
|
||||
<CheckboxGroup :value="formDatum.project_add_permission || []" @on-change="onProjectAddPermissionChange">
|
||||
<Checkbox label="all">{{$L('所有人')}}</Checkbox>
|
||||
<Checkbox label="departmentOwner">{{$L('部门负责人')}}</Checkbox>
|
||||
<Checkbox label="appoint">{{$L('指定人员')}}</Checkbox>
|
||||
</CheckboxGroup>
|
||||
<div v-if="projectAddAll" class="form-tip">{{$L('所有人:所有成员均可创建项目。')}}</div>
|
||||
<div v-else class="form-tip form-list">
|
||||
<p>{{$L('可创建项目的人员')}}:</p>
|
||||
<ol>
|
||||
<li>{{$L('系统管理员(始终可创建,不受开关限制)。')}}</li>
|
||||
<li v-if="(formDatum.project_add_permission || []).includes('departmentOwner')">{{$L('部门负责人与部门管理员。')}}</li>
|
||||
<li v-if="(formDatum.project_add_permission || []).includes('appoint')">{{$L('下方指定的人员。')}}</li>
|
||||
</ol>
|
||||
</div>
|
||||
<template v-if="(formDatum.project_add_permission || []).includes('appoint')">
|
||||
<UserSelect v-model="formDatum.project_add_userids" :multiple-max="200" avatar-name show-disable :title="$L('请选择指定人员')" style="margin-top:6px"/>
|
||||
<div class="form-tip">{{$L('指定人员最多可选择200人')}}</div>
|
||||
</template>
|
||||
</FormItem>
|
||||
<FormItem :label="$L('部门负责人视角')" prop="department_owner_project_view">
|
||||
<RadioGroup v-model="formDatum.department_owner_project_view">
|
||||
<Radio label="open">{{$L('开启')}}</Radio>
|
||||
@ -316,10 +336,13 @@
|
||||
|
||||
<script>
|
||||
import {mapState} from "vuex";
|
||||
import UserSelect from "../../../../components/UserSelect.vue";
|
||||
|
||||
export default {
|
||||
name: 'SystemSetting',
|
||||
|
||||
components: {UserSelect},
|
||||
|
||||
data() {
|
||||
return {
|
||||
loadIng: 0,
|
||||
@ -334,9 +357,26 @@ export default {
|
||||
|
||||
computed: {
|
||||
...mapState(['formOptions']),
|
||||
|
||||
projectAddAll() {
|
||||
return (this.formDatum.project_add_permission || []).includes('all');
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onProjectAddPermissionChange(value) {
|
||||
const prev = this.formDatum.project_add_permission || [];
|
||||
let next = value;
|
||||
if (value.includes('all') && value.length > 1) {
|
||||
// “所有人”与其它范围互斥
|
||||
next = prev.includes('all') ? value.filter(v => v !== 'all') : ['all'];
|
||||
}
|
||||
if (next.length === 0) {
|
||||
next = ['all'];
|
||||
}
|
||||
this.$set(this.formDatum, 'project_add_permission', next);
|
||||
},
|
||||
|
||||
submitForm() {
|
||||
this.$refs.formDatum.validate((valid) => {
|
||||
if (valid) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user