组织管理

dev
郑皇 4 years ago
parent daf86f30ee
commit 51a43af100

@ -1,263 +0,0 @@
<template>
<layout-content
:header="formType == 'add' ? $t('menu.create') : $t('menu.modify')"
back-name="system-menu"
>
<el-form
ref="menuForm"
:model="form"
:rules="rule"
size="small"
label-width="auto"
label-position="right"
>
<el-form-item :label="$t('menu.menu_type')" prop="type">
<el-radio-group
v-model="form.type"
size="mini"
:disabled="formType !== 'add'"
>
<el-radio-button label="0">{{
$t("commons.catalogue")
}}</el-radio-button>
<el-radio-button label="1">{{ $t("commons.menu") }}</el-radio-button>
<el-radio-button label="2">{{
$t("commons.button")
}}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="form.type === 1 && form.icon"
:label="$t('commons.icon')"
prop="icon"
>
<el-popover
placement="bottom-start"
width="425"
trigger="click"
@show="$refs['iconSelect'].reset()"
>
<IconSelect ref="iconSelect" @selected="selected" />
<el-input
slot="reference"
v-model="form.icon"
:placeholder="$t('menu.select_icon')"
readonly
>
<svg-icon
v-if="form.icon"
slot="prefix"
:icon-class="form.icon"
class="el-input__icon"
style="height: 32px; width: 16px"
/>
<i v-else slot="prefix" class="el-icon-search el-input__icon" />
</el-input>
</el-popover>
</el-form-item>
<el-form-item
v-if="form.type !== 2"
:label="$t('menu.tile')"
prop="title"
>
<el-input v-model="form.title" :placeholder="$t('menu.tile')" />
</el-form-item>
<el-form-item
v-if="form.type === 2"
:label="$t('menu.button_name')"
prop="title"
>
<el-input v-model="form.title" :placeholder="$t('menu.button_name')" />
</el-form-item>
<el-form-item
v-if="form.type !== 2"
:label="$t('menu.menu_sort')"
prop="menuSort"
>
<el-input-number
v-model.number="form.menuSort"
:min="0"
:max="999"
controls-position="right"
/>
</el-form-item>
<el-form-item :label="$t('menu.parent_category')" prop="pid">
<treeselect
v-model="form.pid"
:disabled="formType !== 'add'"
:options="menus"
:load-options="loadMenus"
:placeholder="$t('menu.parent_category')"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="save">{{
$t("commons.reset")
}}</el-button>
<el-button @click="reset">{{ $t("commons.confirm") }}</el-button>
</el-form-item>
</el-form>
</layout-content>
</template>
<script>
import LayoutContent from "@/components/business/LayoutContent";
import Treeselect from "@riophae/vue-treeselect";
import IconSelect from "@/components/IconSelect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {
LOAD_CHILDREN_OPTIONS,
LOAD_ROOT_OPTIONS,
} from "@riophae/vue-treeselect";
import {
addMenu,
editMenu,
getMenusTree,
treeByMenuId,
} from "@/api/system/dept";
export default {
components: { LayoutContent, Treeselect, IconSelect },
data() {
return {
topMunu: { id: 0, label: "顶级目录", children: null },
defaultForm: {
menuId: null,
title: null,
menuSort: 999,
path: null,
component: null,
componentName: null,
iframe: false,
pid: 0,
icon: null,
cache: false,
hidden: false,
type: 0,
permission: null,
},
form: {},
rule: {
name: [
{
required: true,
message: this.$t("organization.input_name"),
trigger: "blur",
},
{
min: 2,
max: 25,
message: this.$t("commons.input_limit", [2, 25]),
trigger: "blur",
},
],
description: [
{
max: 50,
message: this.$t("commons.input_limit", [0, 50]),
trigger: "blur",
},
],
},
menus: null,
maps: new Map(),
formType: "add",
};
},
created() {
if (
this.$router.currentRoute.params &&
this.$router.currentRoute.params.menuId
) {
const row = this.$router.currentRoute.params;
this.edit(row);
} else {
this.create();
}
this.initData();
},
methods: {
create() {
this.formType = "add";
this.form = Object.assign({}, this.defaultForm);
},
edit(row) {
this.formType = "modify";
this.form = Object.assign({}, row);
this.initMenuTree();
},
initMenuTree() {
treeByMenuId(this.form.pid || 0).then((res) => {
const results = res.data.map((node) => {
if (node.hasChildren && !node.children) {
node.children = null;
}
return node;
});
this.menus = results;
});
},
//
loadMenus({ action, parentNode, callback }) {
if (action === LOAD_ROOT_OPTIONS) {
const _self = this;
!this.menus &&
getMenusTree("0").then((res) => {
_self.menus = res.data.map((node) => _self.normalizer(node));
callback();
});
}
if (action === LOAD_CHILDREN_OPTIONS) {
const _self = this;
getMenusTree(parentNode.id).then((res) => {
parentNode.children = res.data.map(function (obj) {
return _self.normalizer(obj);
});
callback();
});
}
},
initData() {
this.menus = [];
this.menus.push(this.topMunu);
},
normalizer(node) {
if (node.hasChildren) {
node.children = null;
}
return {
id: node.menuId,
label: node.title,
children: node.children,
};
},
selected(name) {
this.form.icon = name;
},
reset() {
this.$refs.menuForm.resetFields();
},
save() {
this.$refs.menuForm.validate((valid) => {
if (valid) {
const method = this.formType === "add" ? addMenu : editMenu;
method(this.form).then((res) => {
this.$success(this.$t("commons.save_success"));
this.backToList();
});
} else {
return false;
}
});
},
backToList() {
this.$router.push({ name: "system-menu" });
},
},
};
</script>

@ -1,26 +1,244 @@
<template>
<div>
<async-component
url="http://localhost:9528/static/SystemDeptForm.js"
></async-component>
</div>
<layout-content
:header="formType == 'add' ? $t('organization.create') : $t('organization.modify')"
back-name="system-dept"
>
<el-form ref="deptForm" :model="form" :rules="rule" size="small" label-width="auto" label-position="right">
<el-form-item :label="$t('organization.name')" prop="name">
<el-input v-model="form.name" :placeholder="$t('organization.name')" />
</el-form-item>
<el-form-item :label="$t('organization.sort')" prop="deptSort">
<el-input-number v-model="form.deptSort" :min="0" :max="999" controls-position="right" :placeholder="$t('organization.sort')" />
</el-form-item>
<el-form-item :label="$t('organization.top_org')" prop="top">
<el-radio-group v-model="form.top" @change="topChange">
<el-radio-button :label="true">{{ $t('commons.yes') }}</el-radio-button>
<el-radio-button :label="false">{{ $t('commons.no') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.pid !== 0" :label="$t('organization.parent_org')" prop="pid">
<treeselect
v-model="form.pid"
:auto-load-root-options="false"
:options="depts"
:load-options="loadDepts"
:placeholder="$t('organization.select_parent_org')"
@select="nodeChange"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="save">{{ $t('commons.reset') }}</el-button>
<el-button @click="reset">{{ $t('commons.confirm') }}</el-button>
</el-form-item>
</el-form>
</layout-content>
</template>
<script>
import AsyncComponent from "@/components/AsyncComponent";
import LayoutContent from '@/components/business/LayoutContent'
import Treeselect from '@riophae/vue-treeselect'
import IconSelect from '@/components/IconSelect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import {
LOAD_CHILDREN_OPTIONS,
LOAD_ROOT_OPTIONS
} from '@riophae/vue-treeselect'
import {
addMenu,
editMenu,
getMenusTree,
treeByMenuId
} from '@/api/system/dept'
import { execute } from '@/api/system/dynamic'
export default {
name: "SystemDept",
components: {
AsyncComponent,
},
name: 'SystemDeptForm',
components: { LayoutContent },
data() {
return {};
return {
defaultForm: { deptId: null, top: true, pid: null },
maps: new Map(),
form: {},
rule: {
name: [{ required: true, message: this.$t('organization.input_name'), trigger: 'blur' }, { min: 2, max: 25, message: this.$t('commons.input_limit', [2, 25]), trigger: 'blur' }],
description: [{ max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' }]
},
depts: null,
formType: 'add',
pLabel: this.$t('dept.root_org')
}
},
mounted() {},
methods: {},
};
</script>
<style scoped>
</style>
created() {
if (this.$router.currentRoute.params && this.$router.currentRoute.params.deptId) {
var row = this.$router.currentRoute.params
this.edit(row)
} else {
this.create()
}
this.setLoyoutInfo()
},
mounted() {
this.bindKey()
},
destroyed() {
this.unBindKey()
},
methods: {
entryKey(event) {
var keyCode = event.keyCode
if (keyCode === 13) {
this.save()
}
},
bindKey() {
document.addEventListener('keypress', this.entryKey)
},
unBindKey() {
document.removeEventListener('keypress', this.entryKey)
},
executeAxios(url, type, data, callBack) {
var param = {
url: url,
type: type,
data: data,
callBack: callBack
}
execute(param)
.then(function(res) {
if (param.callBack) {
param.callBack(res)
}
})
.catch(function(e) {
if (param.error) {
param.error(e)
}
})
},
setLoyoutInfo() {
this.$emit('on-plugin-layout', {
header: this.formType === 'add' ? this.$t('organization.create') : this.$t('organization.modify'),
backName: 'system-dept'
})
},
create() {
this.formType = 'add'
this.form = Object.assign({}, this.defaultForm)
},
edit(row) {
this.formType = 'modify'
this.form = Object.assign({}, row)
this.initDeptTree()
},
initDeptTree() {
var _this = this
this.executeAxios('/plugin/dept/nodesByDeptId/' + (this.form.pid || 0), 'post', {}, function(res) {
var results = res.data.map(function(node) {
if (node.hasChildren && !node.children) {
node.children = null
}
return node
})
_this.depts = results
})
},
//
loadDepts(_ref) {
var action = _ref.action
var parentNode = _ref.parentNode
var callback = _ref.callback
if (action === 'LOAD_ROOT_OPTIONS' && !this.form.pid) {
var _self = this
this.executeAxios('/plugin/dept/nodesByDeptId/' + 0, 'post', {}, function(res) {
var results = res.data.map(function(node) {
if (node.hasChildren && !node.children) {
node.children = null
}
return node
})
_self.depts = _self.excludeSelf(results)
callback()
})
}
if (action === 'LOAD_CHILDREN_OPTIONS') {
var _self2 = this
this.executeAxios('/plugin/dept/childNodes/' + parentNode.id, 'post', {}, function(res) {
var kids = res.data.map(function(obj) {
return _self2.normalizer(obj)
})
parentNode.children = _self2.excludeSelf(kids)
callback()
})
}
},
normalizer(node) {
if (node.hasChildren) {
node.children = null
}
return {
id: node.deptId,
label: node.name,
children: node.children
}
},
topChange(value) {
if (!value) {
this.form.pid = null
this.depts = null
this.pLabel = this.$t('dept.root_org')
}
},
reset() {
if (this.formType !== 'add') {
var row = this.$router.currentRoute.params
this.edit(row)
} else {
this.$refs.deptForm.resetFields()
}
},
save() {
var _this2 = this
this.$refs.deptForm.validate(function(valid) {
if (valid) {
var url = _this2.formType === 'add' ? '/plugin/dept/create' : '/plugin/dept/update'
_this2.executeAxios(url, 'post', _this2.form, function(res) {
if (res.data && res.data === -2) {
var msg = _this2.pLabel + _this2.$t('dept.name_exist_pre') + _this2.form.name + _this2.$t('dept.name_exist_suf')
_this2.$warning(msg)
return
}
_this2.$success(_this2.$t('commons.save_success'))
_this2.backToList()
})
} else {
return false
}
})
},
backToList() {
this.$router.push({ name: 'system-dept' })
},
excludeSelf(nodes) {
var _this3 = this
if (this.formType !== 'modify') return nodes
nodes.forEach(function(node) {
return node.id === _this3.form.deptId && (node.isDisabled = true)
})
return nodes
},
nodeChange(node, instanceId) {
if (node.label) {
this.pLabel = node.label
}
// console.log(node)
console.log(instanceId)
}
}
}
</script>

@ -1,26 +1,443 @@
<template>
<div>
<async-component
url="http://localhost:9528/static/SystemDept.js"
></async-component>
</div>
<layout-content
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
>
<tree-table
:columns="columns"
:search-config="searchConfig"
@search="search"
>
<template #toolbar>
<el-button
v-permission="['dept:add']"
icon="el-icon-circle-plus-outline"
@click="create"
>{{ $t("organization.create") }}</el-button>
</template>
<el-table
ref="table"
:class="'de-dept-table-class'"
:style="{'width':'100%'}"
:data="tableData"
lazy
:load="loadExpandDatas"
:indent="30"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
row-key="deptId"
>
<!-- <el-table-column type="selection" fix /> -->
<el-table-column
:show-overflow-tooltip="true"
:label="$t('organization.name')"
prop="name"
>
<template slot-scope="scope">
<span :data-id="scope.row.deptId" class="dept-name" :class="(scope.row.subCount === 0 && scope.row.pid === 0) ? 'indent-no-child': ''" @drop="endDrag" @dragover="allowDrop">
<span :id="scope.row.deptId" :draggable="true" @dragstart="startDrag">
{{ scope.row.name }}
</span>
</span></template>
</el-table-column>
<el-table-column
prop="subCount"
:label="$t('organization.sub_organizations')"
align="center"
/>
<el-table-column
prop="createTime"
:label="$t('organization.create_time')"
align="center"
>
<template slot-scope="scope">
<span :data-id="scope.row.deptId" class="dept-name" :class="(scope.row.subCount === 0 && scope.row.pid === 0) ? 'indent-no-child': ''" @drop="endDrag" @dragover="allowDrop">
{{ scope.row.createTime | timestampFormatDate }}
</span>
</template>
</el-table-column>
<fu-table-operations
:buttons="buttons"
:label="$t('commons.operating')"
fix
/>
</el-table>
</tree-table>
</layout-content>
</template>
<script>
import AsyncComponent from "@/components/AsyncComponent";
import LayoutContent from '@/components/business/LayoutContent'
import TreeTable from '@/components/business/tree-table'
// import { checkPermission } from '@/utils/permission'
import IconSelect from '@/components/IconSelect'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import {
LOAD_CHILDREN_OPTIONS,
LOAD_ROOT_OPTIONS
} from '@riophae/vue-treeselect'
import { checkPermission } from '@/utils/permission'
import { getDeptTree, loadTable, treeByDeptId } from '@/api/system/dept'
import { formatCondition, formatQuickCondition } from '@/utils/index'
import { execute } from '@/api/system/dynamic'
export default {
name: "SystemDept",
name: 'SystemDept',
components: {
AsyncComponent,
TreeTable,
LayoutContent
},
data() {
return {};
return {
depts: null,
tableData: [],
maps: new Map(),
permission: {
add: ['dept:add'],
edit: ['dept:edit'],
del: ['dept:del']
},
header: '',
columns: [],
buttons: [
{
label: this.$t('commons.edit'),
icon: 'el-icon-edit',
type: 'primary',
click: this.edit,
show: this.checkPermission(['dept:edit'])
},
{
label: this.$t('commons.delete'),
icon: 'el-icon-delete',
type: 'danger',
click: this._handleDelete,
disabled: this.btnDisabled,
show: this.checkPermission(['dept:del'])
}
],
searchConfig: {
useQuickSearch: true,
quickPlaceholder: this.$t('organization.search_by_name'),
components: [
{
field: 'name',
label: this.$t('organization.name'),
component: 'DeComplexInput'
}
]
},
defaultCondition: {
field: 'pid',
operator: 'eq',
value: 0
}
}
},
mounted() {
this.form = Object.assign({}, this.defaultForm)
this.search()
console.log('dept tree has inited')
},
mounted() {},
methods: {},
};
methods: {
executeAxios(url, type, data, callBack) {
var param = {
url: url,
type: type,
data: data,
callBack: callBack
}
execute(param)
.then(function(res) {
if (param.callBack) {
param.callBack(res)
}
})
.catch(function(e) {
if (param.error) {
param.error(e)
}
})
},
create() {
this.$router.push({ name: 'system-dept-form' })
},
edit(row) {
this.$router.push({ name: 'system-dept-form', params: row })
},
//
search(condition) {
const _this = this
if (condition) {
condition.quick = { value: condition.name }
}
condition = formatQuickCondition(condition, 'name')
if (condition && condition.name && condition.name.field) {
condition = { name: condition.name }
}
let conditionExist = false
const temp = formatCondition(condition)
this.tableData = []
let param = {}
if (temp && temp.conditions && temp.conditions.length !== 0) {
conditionExist = true
param = temp
} else {
param = { conditions: [this.defaultCondition] }
}
this.executeAxios('/plugin/dept/search', 'post', param, function(res) {
let data = res.data
data = data.map(function(obj) {
if (obj.subCount > 0) {
obj.hasChildren = true
}
return obj
})
if (conditionExist) {
data = data.map(function(node) {
delete node.hasChildren
return node
})
_this.tableData = _this.buildTree(data)
_this.$nextTick(function() {
data.forEach(function(node) {
_this.$refs.table.toggleRowExpansion(node, true)
})
})
} else {
_this.tableData = data
}
_this.depts = null
})
},
buildTree(arrs) {
var idMapping = arrs.reduce(function(acc, el, i) {
acc[el.deptId] = i
return acc
}, {})
var roots = []
console.log(123123, arrs)
arrs.forEach(function(el) {
//
if (el.pid === null || el.pid === 0) {
roots.push(el)
return
}
//
var parentEl = arrs[idMapping[el.pid]]
// `children`
parentEl.children = parentEl.children || []
parentEl.children = [...parentEl.children, ...el]
})
console.log(333, roots)
return roots
},
//
loadExpandDatas(row, treeNode, resolve) {
var _this2 = this
this.executeAxios(
'/plugin/dept/childNodes/' + row.deptId,
'post',
{},
function(res) {
var data = res.data
data = data.map(function(obj) {
if (obj.subCount > 0) {
obj.hasChildren = true
}
return obj
})
_this2.maps.set(row.deptId, {
row: row,
treeNode: treeNode,
resolve: resolve
})
resolve && resolve(data)
}
)
},
_handleDelete(organization) {
var _this3 = this
this.$confirm(this.$t('organization.delete_confirm'), '', {
confirmButtonText: this.$t('commons.confirm'),
cancelButtonText: this.$t('commons.cancel'),
type: 'warning'
})
.then(function() {
var requests = [
{ deptId: organization.deptId, pid: organization.pid }
]
_this3.executeAxios(
'/plugin/dept/delete',
'post',
requests,
function(res) {
_this3.$success(_this3.$t('commons.delete_success'))
_this3.search()
_this3.reloadByPid(organization.pid)
}
)
})
.catch(function() {
_this3.$message({
type: 'info',
message: _this3.$t('commons.delete_cancelled')
})
})
},
reloadByPid(pid) {
if (pid !== 0 && this.maps.get(pid)) {
var _maps$get = this.maps.get(pid)
var row = _maps$get.row
var treeNode = _maps$get.treeNode
var resolve = _maps$get.resolve
this.$set(this.$refs.table.store.states.lazyTreeNodeMap, pid, [])
this.loadExpandDatas(row, treeNode, resolve)
}
},
btnDisabled(row) {
return row.deptId === 1 || row.subCount > 0
},
startDrag(ev) {
ev.dataTransfer.setData('sourceId', ev.target.id)
},
allowDrop(ev) {
ev.preventDefault()
},
endDrag(ev) {
ev.preventDefault()
var targetId = ev.target.id
var sourceId = ev.dataTransfer.getData('sourceId')
this.nodeMoveHandler(sourceId, targetId)
},
nodeMoveHandler(resourceId, targetId) {
var _this4 = this
if (!resourceId || !targetId) return
resourceId = parseInt(resourceId)
targetId = parseInt(targetId)
var parent = this.getParent(resourceId)
var pid = parent ? parent.id || parent.deptId : null
// if (!pid) {
// return
// }
// console.log('pid = ' + pid + ', targetId = ' + targetId)
if (this.isParentNoChange(pid, targetId)) {
this.$warning(this.$t('dept.can_not_move_change_sort'))
return
}
if (this.isParent2Children(resourceId, targetId)) {
this.$warning(this.$t('dept.can_not_move_parent_to_children'))
return
}
var param = {
resourceId: resourceId,
targetId: targetId
}
this.executeAxios('/plugin/dept/move', 'post', param, function(res) {
_this4.$success(_this4.$t('dept.move_success'))
_this4.search()
_this4.reloadByPid(targetId)
if (pid) {
_this4.reloadByPid(pid)
}
})
},
//
isParent2Children(resourceId, targetId) {
var currentId = targetId
while (currentId) {
if (resourceId === currentId) {
//
return true
}
var parent = void 0
if ((parent = this.getParent(currentId)) === null) {
//
return false
}
currentId = parent.id || parent.deptId
}
},
//
isParentNoChange(pid, targetId) {
return pid === targetId
},
// deptIdparent
getParent(id) {
var currentNode = this.getNodeWithId(id)
if (!currentNode || !currentNode.pid) {
return null
}
return this.getNodeWithId(currentNode.pid)
},
getNodeWithId(id) {
for (var index = 0; index < this.tableData.length; index++) {
var element = this.tableData[index]
if ((element.id || element.deptId) === id) {
return element
}
}
var lazyTreeNodeMap = this.$refs.table.store.states.lazyTreeNodeMap
for (var key in lazyTreeNodeMap) {
if (Object.hasOwnProperty.call(lazyTreeNodeMap, key)) {
var childNodes = lazyTreeNodeMap[key]
for (var i = 0; i < childNodes.length; i++) {
var node = childNodes[i]
if ((node.id || node.deptId) === id) {
return node
}
}
}
}
return null
}
}
}
</script>
<style scoped>
.member-size {
text-decoration: underline;
}
.org-member-id {
float: left;
}
.org-member-email {
float: right;
color: #8492a6;
font-size: 13px;
}
.select-width {
width: 100%;
}
.dialog-css >>> .el-dialog__header {
padding: 0;
}
::v-deep .el-input-number .el-input__inner {
text-align: left;
}
::v-deep .vue-treeselect__control,
::v-deep .vue-treeselect__placeholder,
::v-deep .vue-treeselect__single-value {
height: 30px;
line-height: 30px;
}
</style>

@ -1,423 +0,0 @@
<template>
<layout-content
v-loading="$store.getters.loadingMap[$store.getters.currentPath]"
>
<tree-table
:columns="columns"
:search-config="searchConfig"
@search="search"
>
<template #toolbar>
<el-button
v-permission="['dept:add']"
icon="el-icon-circle-plus-outline"
@click="create"
>{{ $t("organization.create") }}</el-button
>
</template>
<el-table
ref="table"
:data="tableData"
lazy
:load="search"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
row-key="deptId"
>
<!-- <el-table-column type="selection" fix /> -->
<el-table-column
:show-overflow-tooltip="true"
:label="$t('organization.name')"
prop="name"
/>
<el-table-column
prop="sub_count"
:label="$t('organization.sub_organizations')"
align="center"
/>
<fu-table-operations
:buttons="buttons"
:label="$t('commons.operating')"
fix
/>
</el-table>
</tree-table>
</layout-content>
</template>
<script>
import LayoutContent from "@/components/business/LayoutContent";
import TreeTable from "@/components/business/tree-table";
// import { checkPermission } from '@/utils/permission'
import IconSelect from "@/components/IconSelect";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {
LOAD_CHILDREN_OPTIONS,
LOAD_ROOT_OPTIONS,
} from "@riophae/vue-treeselect";
import { checkPermission } from "@/utils/permission";
import { getDeptTree, loadTable, treeByDeptId } from "@/api/system/dept";
import { formatCondition, formatQuickCondition } from "@/utils/index";
import { execute } from "@/api/system/dynamic";
export default {
name: "SystemDept",
components: {
TreeTable,
LayoutContent,
},
data() {
return {
depts: null,
tableData: [],
maps: new Map(),
permission: {
add: ["dept:add"],
edit: ["dept:edit"],
del: ["dept:del"],
},
header: "",
columns: [],
buttons: [
{
label: this.$t("commons.edit"),
icon: "el-icon-edit",
type: "primary",
click: this.edit,
show: this.checkPermission(["dept:edit"]),
},
{
label: this.$t("commons.delete"),
icon: "el-icon-delete",
type: "danger",
click: this._handleDelete,
disabled: this.btnDisabled,
show: this.checkPermission(["dept:del"]),
},
],
searchConfig: {
useQuickSearch: true,
quickPlaceholder: this.$t("organization.search_by_name"),
components: [
{
field: "name",
label: this.$t("organization.name"),
component: "DeComplexInput",
},
],
},
defaultCondition: {
field: "pid",
operator: "eq",
value: 0,
},
};
},
mounted() {
this.form = Object.assign({}, this.defaultForm);
this.search();
console.log("dept tree has inited");
},
methods: {
executeAxios(url, type, data, callBack) {
var param = {
url: url,
type: type,
data: data,
callBack: callBack,
};
execute(param)
.then(function (res) {
if (param.callBack) {
param.callBack(res);
}
})
.catch(function (e) {
if (param.error) {
param.error(e);
}
});
},
create() {
this.$router.push({ name: "system-dept-form" });
},
edit(row) {
this.$router.push({ name: "system-dept-form", params: row });
},
//
search(condition) {
const _this = this;
if (condition) {
condition.quick = { value: condition.name };
}
condition = formatQuickCondition(condition, "name");
if (condition && condition.name && condition.name.field) {
condition = { name: condition.name };
}
let conditionExist = false;
const temp = formatCondition(condition);
this.tableData = [];
let param = {};
if (temp && temp.conditions && temp.conditions.length !== 0) {
conditionExist = true;
param = temp;
} else {
param = { conditions: [this.defaultCondition] };
}
this.executeAxios("/plugin/dept/search", "post", param, function (res) {
let data = res.data;
data = data.map(function (obj) {
if (obj.subCount > 0) {
obj.hasChildren = true;
}
return obj;
});
if (conditionExist) {
data = data.map(function (node) {
delete node.hasChildren;
return node;
});
_this.tableData = _this.buildTree(data);
_this.$nextTick(function () {
data.forEach(function (node) {
_this.$refs.table.toggleRowExpansion(node, true);
});
});
} else {
_this.tableData = data;
}
_this.depts = null;
});
},
buildTree(arrs) {
var idMapping = arrs.reduce(function (acc, el, i) {
acc[el.deptId] = i;
return acc;
}, {});
var roots = [];
console.log(123123, arrs);
arrs.forEach(function (el) {
//
if (el.pid === null || el.pid === 0) {
roots.push(el);
return;
}
//
var parentEl = arrs[idMapping[el.pid]];
// `children`
parentEl.children = parentEl.children || [];
parentEl.children = [...parentEl.children, ...el];
});
console.log(333, roots);
return roots;
},
//
loadExpandDatas(row, treeNode, resolve) {
var _this2 = this;
this.executeAxios(
"/plugin/dept/childNodes/" + row.deptId,
"post",
{},
function (res) {
var data = res.data;
data = data.map(function (obj) {
if (obj.subCount > 0) {
obj.hasChildren = true;
}
return obj;
});
_this2.maps.set(row.deptId, {
row: row,
treeNode: treeNode,
resolve: resolve,
});
resolve && resolve(data);
}
);
},
_handleDelete(organization) {
var _this3 = this;
this.$confirm(this.$t("organization.delete_confirm"), "", {
confirmButtonText: this.$t("commons.confirm"),
cancelButtonText: this.$t("commons.cancel"),
type: "warning",
})
.then(function () {
var requests = [
{ deptId: organization.deptId, pid: organization.pid },
];
_this3.executeAxios(
"/plugin/dept/delete",
"post",
requests,
function (res) {
_this3.$success(_this3.$t("commons.delete_success"));
_this3.search();
_this3.reloadByPid(organization.pid);
}
);
})
.catch(function () {
_this3.$message({
type: "info",
message: _this3.$t("commons.delete_cancelled"),
});
});
},
reloadByPid(pid) {
if (pid !== 0 && this.maps.get(pid)) {
var _maps$get = this.maps.get(pid);
var row = _maps$get.row;
var treeNode = _maps$get.treeNode;
var resolve = _maps$get.resolve;
this.$set(this.$refs.table.store.states.lazyTreeNodeMap, pid, []);
this.loadExpandDatas(row, treeNode, resolve);
}
},
btnDisabled(row) {
return row.deptId === 1 || row.subCount > 0;
},
startDrag(ev) {
ev.dataTransfer.setData("sourceId", ev.target.id);
},
allowDrop(ev) {
ev.preventDefault();
},
endDrag(ev) {
ev.preventDefault();
var targetId = ev.target.id;
var sourceId = ev.dataTransfer.getData("sourceId");
this.nodeMoveHandler(sourceId, targetId);
},
nodeMoveHandler(resourceId, targetId) {
var _this4 = this;
if (!resourceId || !targetId) return;
resourceId = parseInt(resourceId);
targetId = parseInt(targetId);
var parent = this.getParent(resourceId);
var pid = parent ? parent.id || parent.deptId : null;
// if (!pid) {
// return
// }
// console.log('pid = ' + pid + ', targetId = ' + targetId)
if (this.isParentNoChange(pid, targetId)) {
this.$warning(this.$t("dept.can_not_move_change_sort"));
return;
}
if (this.isParent2Children(resourceId, targetId)) {
this.$warning(this.$t("dept.can_not_move_parent_to_children"));
return;
}
var param = {
resourceId: resourceId,
targetId: targetId,
};
this.executeAxios("/plugin/dept/move", "post", param, function (res) {
_this4.$success(_this4.$t("dept.move_success"));
_this4.search();
_this4.reloadByPid(targetId);
if (pid) {
_this4.reloadByPid(pid);
}
});
},
//
isParent2Children(resourceId, targetId) {
var currentId = targetId;
while (currentId) {
if (resourceId === currentId) {
//
return true;
}
var parent = void 0;
if ((parent = this.getParent(currentId)) === null) {
//
return false;
}
currentId = parent.id || parent.deptId;
}
},
//
isParentNoChange(pid, targetId) {
return pid === targetId;
},
// deptIdparent
getParent(id) {
var currentNode = this.getNodeWithId(id);
if (!currentNode || !currentNode.pid) {
return null;
}
return this.getNodeWithId(currentNode.pid);
},
getNodeWithId(id) {
for (var index = 0; index < this.tableData.length; index++) {
var element = this.tableData[index];
if ((element.id || element.deptId) === id) {
return element;
}
}
var lazyTreeNodeMap = this.$refs.table.store.states.lazyTreeNodeMap;
for (var key in lazyTreeNodeMap) {
if (Object.hasOwnProperty.call(lazyTreeNodeMap, key)) {
var childNodes = lazyTreeNodeMap[key];
for (var i = 0; i < childNodes.length; i++) {
var node = childNodes[i];
if ((node.id || node.deptId) === id) {
return node;
}
}
}
}
return null;
},
},
};
</script>
<style scoped>
.member-size {
text-decoration: underline;
}
.org-member-id {
float: left;
}
.org-member-email {
float: right;
color: #8492a6;
font-size: 13px;
}
.select-width {
width: 100%;
}
.dialog-css >>> .el-dialog__header {
padding: 0;
}
::v-deep .el-input-number .el-input__inner {
text-align: left;
}
::v-deep .vue-treeselect__control,
::v-deep .vue-treeselect__placeholder,
::v-deep .vue-treeselect__single-value {
height: 30px;
line-height: 30px;
}
</style>
Loading…
Cancel
Save