mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-14 04:32:49 +00:00
perf: 优化团队部门支持3级部门
This commit is contained in:
parent
cfd2e1fd7b
commit
36cdf87bfe
@ -1653,19 +1653,22 @@ class UsersController extends AbstractController
|
|||||||
if (empty($parentDepartment)) {
|
if (empty($parentDepartment)) {
|
||||||
return Base::retError('上级部门不存在或已被删除');
|
return Base::retError('上级部门不存在或已被删除');
|
||||||
}
|
}
|
||||||
if ($parentDepartment->parent_id > 0) {
|
if (count($parentDepartment->parents()) > 2) {
|
||||||
return Base::retError('上级部门层级错误');
|
return Base::retError('部门层级最多只能创建3级');
|
||||||
}
|
}
|
||||||
if (UserDepartment::whereParentId($parent_id)->count() > 20) {
|
if ($id > 0 && UserDepartment::whereParentId($id)->whereId($parent_id)->exists()) {
|
||||||
|
return Base::retError('不能选择自己的子部门作为上级部门');
|
||||||
|
}
|
||||||
|
if (UserDepartment::whereParentId($parent_id)->count() >= 20) {
|
||||||
return Base::retError('每个部门最多只能创建20个子部门');
|
return Base::retError('每个部门最多只能创建20个子部门');
|
||||||
}
|
}
|
||||||
if ($id > 0 && UserDepartment::whereParentId($id)->exists()) {
|
|
||||||
return Base::retError('含有子部门无法修改上级部门');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (empty($owner_userid) || !User::whereUserid($owner_userid)->exists()) {
|
if (empty($owner_userid) || !User::whereUserid($owner_userid)->exists()) {
|
||||||
return Base::retError('请选择正确的部门负责人');
|
return Base::retError('请选择正确的部门负责人');
|
||||||
}
|
}
|
||||||
|
if (UserDepartment::whereOwnerUserid($owner_userid)->count() >= 10) {
|
||||||
|
return Base::retError('每个用户最多只能负责10个部门');
|
||||||
|
}
|
||||||
//
|
//
|
||||||
$userDepartment->saveDepartment([
|
$userDepartment->saveDepartment([
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
@ -1674,7 +1677,7 @@ class UsersController extends AbstractController
|
|||||||
], $dialog_useid);
|
], $dialog_useid);
|
||||||
Cache::forever("UserDepartment::rand", Base::generatePassword());
|
Cache::forever("UserDepartment::rand", Base::generatePassword());
|
||||||
//
|
//
|
||||||
return Base::retSuccess($parent_id > 0 ? '保存成功' : '新建成功');
|
return Base::retSuccess($id > 0 ? '保存成功' : '新建成功');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1701,6 +1704,9 @@ class UsersController extends AbstractController
|
|||||||
if (empty($userDepartment)) {
|
if (empty($userDepartment)) {
|
||||||
return Base::retError('部门不存在或已被删除');
|
return Base::retError('部门不存在或已被删除');
|
||||||
}
|
}
|
||||||
|
if (UserDepartment::whereParentId($id)->exists()) {
|
||||||
|
return Base::retError('含有子部门无法删除');
|
||||||
|
}
|
||||||
$userDepartment->deleteDepartment();
|
$userDepartment->deleteDepartment();
|
||||||
Cache::forever("UserDepartment::rand", Base::generatePassword());
|
Cache::forever("UserDepartment::rand", Base::generatePassword());
|
||||||
//
|
//
|
||||||
|
|||||||
@ -34,6 +34,21 @@ use App\Exceptions\ApiException;
|
|||||||
*/
|
*/
|
||||||
class UserDepartment extends AbstractModel
|
class UserDepartment extends AbstractModel
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 获取所有父级部门
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function parents()
|
||||||
|
{
|
||||||
|
$parents = [];
|
||||||
|
$parent = $this;
|
||||||
|
while ($parent) {
|
||||||
|
$parents[] = $parent;
|
||||||
|
$parent = $parent->parent_id ? self::find($parent->parent_id) : null;
|
||||||
|
}
|
||||||
|
return $parents;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存部门
|
* 保存部门
|
||||||
* @param $data
|
* @param $data
|
||||||
@ -131,9 +146,7 @@ class UserDepartment extends AbstractModel
|
|||||||
});
|
});
|
||||||
// 解散群组
|
// 解散群组
|
||||||
$dialog = WebSocketDialog::find($this->dialog_id);
|
$dialog = WebSocketDialog::find($this->dialog_id);
|
||||||
if ($dialog) {
|
$dialog?->deleteDialog();
|
||||||
$dialog->deleteDialog();
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
$this->delete();
|
$this->delete();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,7 @@
|
|||||||
@command="onOpDepartment">
|
@command="onOpDepartment">
|
||||||
<i @click.stop="" class="taskfont department-menu"></i>
|
<i @click.stop="" class="taskfont department-menu"></i>
|
||||||
<EDropdownMenu slot="dropdown">
|
<EDropdownMenu slot="dropdown">
|
||||||
<EDropdownItem v-if="item.level <= 2" :command="`add_${item.id}`">
|
<EDropdownItem v-if="item.level <= 3" :command="`add_${item.id}`">
|
||||||
<div>{{$L('添加子部门')}}</div>
|
<div>{{$L('添加子部门')}}</div>
|
||||||
</EDropdownItem>
|
</EDropdownItem>
|
||||||
<EDropdownItem v-if="item.dialog_id" :command="`dialog_${item.dialog_id}`">
|
<EDropdownItem v-if="item.dialog_id" :command="`dialog_${item.dialog_id}`">
|
||||||
@ -183,11 +183,19 @@
|
|||||||
<Input type="text" v-model="departmentData.name" :placeholder="$L('请输入部门名称')"></Input>
|
<Input type="text" v-model="departmentData.name" :placeholder="$L('请输入部门名称')"></Input>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem prop="parent_id" :label="$L('上级部门')">
|
<FormItem prop="parent_id" :label="$L('上级部门')">
|
||||||
<Select v-model="departmentData.parent_id" :disabled="departmentParentDisabled" :placeholder="$L('请选择上级部门')">
|
<Select v-model="departmentData.parent_id" :placeholder="$L('请选择上级部门')">
|
||||||
<Option :value="0">{{ $L('默认部门') }}</Option>
|
<Option :value="0">
|
||||||
<Option v-for="(item, index) in departmentList" v-if="item.parent_id == 0 && item.id != departmentData.id" :value="item.id" :key="index" :label="item.name"> {{ item.name }}</Option>
|
<div class="team-department-level-name level-1">{{ $L('默认部门') }}</div>
|
||||||
|
</Option>
|
||||||
|
<Option
|
||||||
|
v-for="(item, index) in departmentList"
|
||||||
|
:disabled="item.level > 3 || item.id == departmentData.id || item.parent_id == departmentData.id"
|
||||||
|
:value="item.id"
|
||||||
|
:key="index"
|
||||||
|
:label="item.chains.join(' - ')">
|
||||||
|
<div :class="`team-department-level-name level-${item.level}`">{{ item.name }}</div>
|
||||||
|
</Option>
|
||||||
</Select>
|
</Select>
|
||||||
<div v-if="departmentParentDisabled" class="form-tip" style="margin-bottom:-16px">{{$L('含有子部门无法修改上级部门')}}</div>
|
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem prop="owner_userid" :label="$L('部门负责人')">
|
<FormItem prop="owner_userid" :label="$L('部门负责人')">
|
||||||
<UserSelect v-model="departmentData.owner_userid" :multiple-max="1" :title="$L('请选择部门负责人')"/>
|
<UserSelect v-model="departmentData.owner_userid" :multiple-max="1" :title="$L('请选择部门负责人')"/>
|
||||||
@ -286,8 +294,19 @@
|
|||||||
<Form :model="departmentEditData" v-bind="formOptions" @submit.native.prevent>
|
<Form :model="departmentEditData" v-bind="formOptions" @submit.native.prevent>
|
||||||
<Alert type="error" style="margin-bottom:18px">{{$L(`正在进行帐号【ID:${departmentEditData.userid}, ${departmentEditData.nickname}】部门修改。`)}}</Alert>
|
<Alert type="error" style="margin-bottom:18px">{{$L(`正在进行帐号【ID:${departmentEditData.userid}, ${departmentEditData.nickname}】部门修改。`)}}</Alert>
|
||||||
<FormItem :label="$L('修改部门')">
|
<FormItem :label="$L('修改部门')">
|
||||||
<Select v-model="departmentEditData.department" multiple :multiple-max="10" :placeholder="$L('留空为默认部门')">
|
<Select
|
||||||
<Option v-for="(item, index) in departmentList" :value="item.id" :key="index">{{ item.name }}</Option>
|
v-model="departmentEditData.department"
|
||||||
|
multiple
|
||||||
|
:multiple-max="10"
|
||||||
|
:multiple-max-before="onMultipleMaxBefore"
|
||||||
|
:placeholder="$L('留空为默认部门')">
|
||||||
|
<Option
|
||||||
|
v-for="(item, index) in departmentList"
|
||||||
|
:value="item.id"
|
||||||
|
:key="index"
|
||||||
|
:label="item.chains.join(' - ')">
|
||||||
|
<div :class="`team-department-level-name level-${item.level - 1}`">{{ item.name }}</div>
|
||||||
|
</Option>
|
||||||
</Select>
|
</Select>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</Form>
|
</Form>
|
||||||
@ -515,34 +534,44 @@ export default {
|
|||||||
key: 'department',
|
key: 'department',
|
||||||
minWidth: 80,
|
minWidth: 80,
|
||||||
render: (h, {row}) => {
|
render: (h, {row}) => {
|
||||||
let departments = []
|
const departments = []
|
||||||
row.department.some(did => {
|
row.department.some(did => {
|
||||||
const data = this.departmentList.find(d => d.id == did)
|
const data = this.departmentList.find(d => d.id == did)
|
||||||
if (data) {
|
if (data) {
|
||||||
departments.push(data.name)
|
departments.push({
|
||||||
|
id: data.id,
|
||||||
|
name: data.name,
|
||||||
|
chain: data.chains.join(' - ')
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
departments.sort((a, b) => {
|
||||||
|
return a.id - b.id
|
||||||
|
})
|
||||||
if (departments.length === 0) {
|
if (departments.length === 0) {
|
||||||
return h('AutoTip', this.$L('默认部门'));
|
return h('AutoTip', this.$L('默认部门'));
|
||||||
} else {
|
} else {
|
||||||
const tmp = []
|
const tmp = []
|
||||||
tmp.push(h('span', {
|
tmp.push(h('span', {
|
||||||
domProps: {
|
domProps: {
|
||||||
title: departments[0]
|
title: departments[0].chain
|
||||||
}
|
}
|
||||||
}, departments[0]))
|
}, departments[0].name))
|
||||||
if (departments.length > 1) {
|
if (departments.length > 1) {
|
||||||
departments = departments.splice(1)
|
|
||||||
tmp.push(h('ETooltip', [
|
tmp.push(h('ETooltip', [
|
||||||
h('div', {
|
h('ol', {
|
||||||
slot: 'content',
|
slot: 'content',
|
||||||
|
style: {
|
||||||
|
lineHeight: '1.5',
|
||||||
|
paddingLeft: '18px'
|
||||||
|
},
|
||||||
domProps: {
|
domProps: {
|
||||||
innerHTML: departments.join("<br/>")
|
innerHTML: departments.map(({chain}) => `<li>${chain}</li>`).join('')
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
h('div', {
|
h('div', {
|
||||||
class: 'department-tag-num'
|
class: 'department-tag-num'
|
||||||
}, ` +${departments.length}`)
|
}, departments.length)
|
||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
return h('div', {
|
return h('div', {
|
||||||
@ -910,10 +939,6 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
...mapState(['formOptions']),
|
...mapState(['formOptions']),
|
||||||
|
|
||||||
departmentParentDisabled() {
|
|
||||||
return !!(this.departmentData.id > 0 && this.departmentList.find(({parent_id}) => parent_id == this.departmentData.id));
|
|
||||||
},
|
|
||||||
|
|
||||||
userStyle({minWidth, windowPortrait}) {
|
userStyle({minWidth, windowPortrait}) {
|
||||||
const style = {}
|
const style = {}
|
||||||
if (minWidth > 0 && windowPortrait) {
|
if (minWidth > 0 && windowPortrait) {
|
||||||
@ -1206,23 +1231,29 @@ export default {
|
|||||||
url: 'users/department/list',
|
url: 'users/department/list',
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
this.departmentList = []
|
this.departmentList = []
|
||||||
this.generateDepartmentList(data, 0, 1)
|
this.generateDepartmentList(data, 0, 1, [])
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.departmentLoading--;
|
this.departmentLoading--;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
generateDepartmentList(data, parent_id, level) {
|
generateDepartmentList(data, parent_id, level, chains = []) {
|
||||||
data.some(item => {
|
data.some(item => {
|
||||||
if (item.parent_id == parent_id) {
|
if (item.parent_id == parent_id) {
|
||||||
this.departmentList.push(Object.assign(item, {
|
this.departmentList.push(Object.assign(item, {
|
||||||
|
chains: chains.concat([item.name]),
|
||||||
level: level + 1
|
level: level + 1
|
||||||
}))
|
}))
|
||||||
this.generateDepartmentList(data, item.id, level + 1)
|
this.generateDepartmentList(data, item.id, level + 1, chains.concat([item.name]))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onMultipleMaxBefore(num) {
|
||||||
|
$A.messageError(`最多选择${num}个部门`)
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
onShowDepartment(data) {
|
onShowDepartment(data) {
|
||||||
this.departmentData = Object.assign({
|
this.departmentData = Object.assign({
|
||||||
id: 0,
|
id: 0,
|
||||||
|
|||||||
@ -83,13 +83,13 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
&.level-2 {
|
&.level-2 {
|
||||||
margin-left: 24px;
|
margin-left: 18px;
|
||||||
}
|
}
|
||||||
&.level-3 {
|
&.level-3 {
|
||||||
margin-left: 48px;
|
margin-left: 36px;
|
||||||
}
|
}
|
||||||
&.level-4 {
|
&.level-4 {
|
||||||
margin-left: 72px;
|
margin-left: 54px;
|
||||||
}
|
}
|
||||||
.department-icon {
|
.department-icon {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
@ -155,6 +155,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.team-department-level-name {
|
||||||
|
&.level-2 {
|
||||||
|
margin-left: 18px;
|
||||||
|
}
|
||||||
|
&.level-3 {
|
||||||
|
margin-left: 36px;
|
||||||
|
}
|
||||||
|
&.level-4 {
|
||||||
|
margin-left: 54px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.team-department-add-dialog-group {
|
.team-department-add-dialog-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user