作者 朱兆平

用户岗位/角色/权限树形结构完毕

@@ -12,7 +12,8 @@ Array.prototype.contains = function(obj) { @@ -12,7 +12,8 @@ Array.prototype.contains = function(obj) {
12 } 12 }
13 } 13 }
14 return false; 14 return false;
15 -}, 15 +}
  16 +
16 function padding(s, len) { 17 function padding(s, len) {
17 len = len - (s + '').length; 18 len = len - (s + '').length;
18 for (var i = 0; i < len; i++) { s = '0' + s; } 19 for (var i = 0; i < len; i++) { s = '0' + s; }
@@ -126,7 +126,7 @@ axios.interceptors.response.use( @@ -126,7 +126,7 @@ axios.interceptors.response.use(
126 } 126 }
127 } 127 }
128 // 返回 response 里的错误信息 128 // 返回 response 里的错误信息
129 - let errorInfo = error.data.error ? error.data.error.message : error.data; 129 + let errorInfo = error.response ? error.response.statusText : (error.data.error ? error.data.error.message : error.message);
130 return Promise.reject(errorInfo); 130 return Promise.reject(errorInfo);
131 } 131 }
132 ); 132 );
@@ -16,22 +16,26 @@ @@ -16,22 +16,26 @@
16 </el-col> 16 </el-col>
17 17
18 <!--列表--> 18 <!--列表-->
19 - <el-table :data="tableList" highlight-current-row v-loading="listLoading" @selection-change="selsChange" style="width: 100%;"> 19 + <el-table :data="tableList" highlight-current-row v-loading="listLoading" @selection-change="selsChange" style="width: 100%;"
  20 + row-key="permissionId"
  21 + border
  22 + :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  23 + >
20 <el-table-column type="selection" width="55"> 24 <el-table-column type="selection" width="55">
21 </el-table-column> 25 </el-table-column>
22 - <el-table-column type="index" width="60"> 26 + <!--<el-table-column type="index" width="60">-->
  27 + <!--</el-table-column>-->
  28 + <el-table-column prop="permissionId" label="ID" width="130" sortable>
23 </el-table-column> 29 </el-table-column>
24 - <el-table-column prop="permissionId" label="ID" width="100" sortable> 30 + <el-table-column prop="name" label="权限名称" min-width="150" sortable>
25 </el-table-column> 31 </el-table-column>
26 - <el-table-column prop="name" label="权限名称" min-width="200" sortable> 32 + <el-table-column prop="description" label="描述" min-width="120" sortable>
27 </el-table-column> 33 </el-table-column>
28 - <el-table-column prop="description" label="描述" min-width="200" sortable> 34 + <el-table-column prop="ismenu" label="是否目录" width="100" :formatter="formatState" sortable>
29 </el-table-column> 35 </el-table-column>
30 - <el-table-column prop="permissionOrder" label="排序" width="100" sortable> 36 + <el-table-column prop="url" label="访问路径" width="300" sortable>
31 </el-table-column> 37 </el-table-column>
32 - <el-table-column prop="url" label="路径" width="100" sortable>  
33 - </el-table-column>  
34 - <el-table-column label="操作" min-width="150"> 38 + <el-table-column label="操作" min-width="100">
35 <template slot-scope="scope"> 39 <template slot-scope="scope">
36 <el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button> 40 <el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
37 <el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">删除</el-button> 41 <el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">删除</el-button>
@@ -143,7 +147,7 @@ @@ -143,7 +147,7 @@
143 tableList: [], 147 tableList: [],
144 total: 0, 148 total: 0,
145 pageNum: 1, 149 pageNum: 1,
146 - pageSize: 10, 150 + pageSize: 100,
147 listLoading: false, 151 listLoading: false,
148 sels: [],//列表选中列 152 sels: [],//列表选中列
149 //编辑界面是否显示 153 //编辑界面是否显示
@@ -208,7 +212,7 @@ @@ -208,7 +212,7 @@
208 return row.sex == 1 ? '男' : row.sex == 0 ? '女' : '未知'; 212 return row.sex == 1 ? '男' : row.sex == 0 ? '女' : '未知';
209 }, 213 },
210 formatState: function (row, column) { 214 formatState: function (row, column) {
211 - return row.state == true ? '是' : row.state == false ? '否' : '未知'; 215 + return row.ismenu == true ? '是' : row.ismenu == false ? '否' : '未知';
212 }, 216 },
213 handleCurrentChange(val) { 217 handleCurrentChange(val) {
214 this.pageNum = val; 218 this.pageNum = val;
@@ -23,18 +23,25 @@ @@ -23,18 +23,25 @@
23 :tree-props="{children: 'children', hasChildren: 'hasChildren'}"> 23 :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
24 <el-table-column type="selection" width="55"> 24 <el-table-column type="selection" width="55">
25 </el-table-column> 25 </el-table-column>
26 - <el-table-column type="index" width="60">  
27 - </el-table-column>  
28 - <!--<el-table-column prop="roleId" label="ID" width="100" sortable>--> 26 + <!--<el-table-column type="index" width="60">-->
29 <!--</el-table-column>--> 27 <!--</el-table-column>-->
  28 + <el-table-column prop="roleId" label="ID" width="120">
  29 + </el-table-column>
30 <el-table-column prop="roleName" label="岗位/角色名称" min-width="200" sortable> 30 <el-table-column prop="roleName" label="岗位/角色名称" min-width="200" sortable>
31 </el-table-column> 31 </el-table-column>
32 <!--<el-table-column prop="departmentName" label="部门名称" min-width="200" sortable>--> 32 <!--<el-table-column prop="departmentName" label="部门名称" min-width="200" sortable>-->
33 <!--</el-table-column>--> 33 <!--</el-table-column>-->
34 - <el-table-column prop="description" label="描述" min-width="200" sortable> 34 + <el-table-column prop="description" label="描述" min-width="160" >
  35 + </el-table-column>
  36 + <el-table-column prop="type" label="类型" min-width="80" sortable>
  37 + </el-table-column>
  38 + <el-table-column prop="businessLicense" label="工商代码" min-width="180" >
  39 + </el-table-column>
  40 + <el-table-column prop="customsRegCode" label="海关备案代码" min-width="150" >
35 </el-table-column> 41 </el-table-column>
36 <el-table-column label="操作" min-width="260"> 42 <el-table-column label="操作" min-width="260">
37 <template slot-scope="scope"> 43 <template slot-scope="scope">
  44 + <el-button type="primary" size="small" @click="handleAdd(scope.$index, scope.row)">新增下级</el-button>
38 <el-button size="small" @click="setPerm(scope.$index, scope.row)">设置权限</el-button> 45 <el-button size="small" @click="setPerm(scope.$index, scope.row)">设置权限</el-button>
39 <el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button> 46 <el-button size="small" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
40 <el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">删除</el-button> 47 <el-button type="danger" size="small" @click="handleDel(scope.$index, scope.row)">删除</el-button>
@@ -79,23 +86,37 @@ @@ -79,23 +86,37 @@
79 86
80 <!--新增界面--> 87 <!--新增界面-->
81 <el-dialog title="新增" :visible.sync="addFormVisible" :close-on-click-modal="false"> 88 <el-dialog title="新增" :visible.sync="addFormVisible" :close-on-click-modal="false">
82 - <el-form :model="addForm" label-width="80px" :rules="addFormRules" ref="addForm">  
83 - <el-form-item label="岗位/角色名称" prop="roleName">  
84 - <el-input v-model="addForm.roleName" auto-complete="off" placeholder="请输入岗位/角色名称:例如:ROLE_name"></el-input> 89 + <el-form :model="addForm" label-width="120px" :rules="addFormRules" ref="addForm">
  90 + <el-form-item label="上级组织机构">
  91 + <span>{{addForm.parentName}}</span>
  92 + </el-form-item>
  93 + <el-form-item label="组织机构名称" prop="roleName">
  94 + <el-input v-model="addForm.roleName" auto-complete="off" placeholder="请输入组织机构名称:例如:公司名称"></el-input>
85 </el-form-item> 95 </el-form-item>
86 - <el-form-item label="岗位/角色描述" prop="description">  
87 - <el-input v-model="addForm.description" auto-complete="off" placeholder="请输入岗位/角色描述:例如:用户管理员"></el-input> 96 + <el-form-item label="组织机构描述" prop="description">
  97 + <el-input v-model="addForm.description" auto-complete="off" placeholder="组织机构描述:例如:组织机构简介"></el-input>
88 </el-form-item> 98 </el-form-item>
89 - <el-form-item label="部门名称" prop="roleSign">  
90 - <el-select v-model="addForm.departmentId" placeholder="请选择"> 99 + <el-form-item label="组织机构类型" prop="description">
  100 + <el-select
  101 + v-model="addForm.type"
  102 + filterable
  103 + allow-create
  104 + default-first-option
  105 + placeholder="请选择类型">
91 <el-option 106 <el-option
92 - v-for="item in departmentNameList"  
93 - :key="item.departmentId"  
94 - :label="item.departmentName"  
95 - :value="item.departmentId"> 107 + v-for="item in companyOption"
  108 + :key="item.value"
  109 + :label="item.label"
  110 + :value="item.value">
96 </el-option> 111 </el-option>
97 </el-select> 112 </el-select>
98 </el-form-item> 113 </el-form-item>
  114 + <el-form-item label="工商企业代码" prop="description">
  115 + <el-input v-model="addForm.businessLicense" auto-complete="off" placeholder="社会信用代码或者组织机构代码"></el-input>
  116 + </el-form-item>
  117 + <el-form-item label="海关备案代码" prop="description">
  118 + <el-input v-model="addForm.customsRegCode" auto-complete="off" placeholder="海关备案后返回的备案代码"></el-input>
  119 + </el-form-item>
99 </el-form> 120 </el-form>
100 <div slot="footer" class="dialog-footer"> 121 <div slot="footer" class="dialog-footer">
101 <el-button @click.native="addFormVisible = false">取消</el-button> 122 <el-button @click.native="addFormVisible = false">取消</el-button>
@@ -106,9 +127,11 @@ @@ -106,9 +127,11 @@
106 <!--权限设置界面--> 127 <!--权限设置界面-->
107 <el-dialog title="岗位的权限设置" :visible.sync="PermFormVisible" :close-on-click-modal="false"> 128 <el-dialog title="岗位的权限设置" :visible.sync="PermFormVisible" :close-on-click-modal="false">
108 <el-form :model="permForm" label-width="80px" ref="permForm"> 129 <el-form :model="permForm" label-width="80px" ref="permForm">
109 - <el-checkbox-group v-model="permIds" size="small">  
110 - <el-checkbox v-for="perm in permissons" :label="perm.permissionId" :key="perm.permissionId">{{perm.name}}</el-checkbox>  
111 - </el-checkbox-group> 130 + <el-tree :data="permissons" :props="treeDefaultProps"
  131 + @check="clickDeal"
  132 + show-checkbox highlight-current default-expand-all check-on-click-node check-strictly
  133 + node-key="permissionId" ref="tree">
  134 + </el-tree>
112 </el-form> 135 </el-form>
113 <div slot="footer" class="dialog-footer"> 136 <div slot="footer" class="dialog-footer">
114 <el-button @click.native="PermFormVisible = false">取消</el-button> 137 <el-button @click.native="PermFormVisible = false">取消</el-button>
@@ -131,6 +154,20 @@ @@ -131,6 +154,20 @@
131 filters: { 154 filters: {
132 roleName: '' 155 roleName: ''
133 }, 156 },
  157 + companyOption: [
  158 + {
  159 + label: "集团",
  160 + value: "集团"
  161 + },
  162 + {
  163 + label: "公司",
  164 + value: "公司"
  165 + }
  166 + ],
  167 + treeDefaultProps: {
  168 + children: 'children',
  169 + label: 'name',
  170 + },
134 departmentNameList:[], 171 departmentNameList:[],
135 roles: [], 172 roles: [],
136 permissons: [], 173 permissons: [],
@@ -175,7 +212,12 @@ @@ -175,7 +212,12 @@
175 description: '', 212 description: '',
176 roleName: '', 213 roleName: '',
177 roleSign: 1, 214 roleSign: 1,
178 - departmentId:'' 215 + departmentId:'',
  216 + type: '',
  217 + businessLicense: '',
  218 + customsRegCode: '',
  219 + parentName: ''
  220 +
179 }, 221 },
180 permForm: { 222 permForm: {
181 roleId: 1, 223 roleId: 1,
@@ -228,7 +270,6 @@ @@ -228,7 +270,6 @@
228 270
229 }, 271 },
230 272
231 -  
232 //获取部门列表 273 //获取部门列表
233 getdepartmentNames() { 274 getdepartmentNames() {
234 275
@@ -268,7 +309,11 @@ @@ -268,7 +309,11 @@
268 if(null!= error.response && error.response!==undefined){ 309 if(null!= error.response && error.response!==undefined){
269 let status= error.response.status; 310 let status= error.response.status;
270 let msg = error.response.statusText; 311 let msg = error.response.statusText;
271 - alert(status+msg); 312 + message({
  313 + // 饿了么的消息弹窗组件
  314 + message: status+msg,
  315 + type: "error"
  316 + });
272 }else { 317 }else {
273 alert(error); 318 alert(error);
274 } 319 }
@@ -308,9 +353,10 @@ @@ -308,9 +353,10 @@
308 this.getdepartmentNames(); 353 this.getdepartmentNames();
309 }, 354 },
310 setPerm: function (index, row) { 355 setPerm: function (index, row) {
  356 + this.PermFormVisible = true;
  357 + this.getPermList();
311 var _this = this; 358 var _this = this;
312 this.permIds = []; 359 this.permIds = [];
313 - this.PermFormVisible = true;  
314 this.permForm = Object.assign({}, row); 360 this.permForm = Object.assign({}, row);
315 let rolePerms = this.permForm.permissions; 361 let rolePerms = this.permForm.permissions;
316 if (util.checkNull(rolePerms)){ 362 if (util.checkNull(rolePerms)){
@@ -320,22 +366,36 @@ @@ -320,22 +366,36 @@
320 } 366 }
321 }); 367 });
322 } 368 }
323 - this.getPermList(); 369 +
  370 + this.$nextTick(() => {
  371 +
  372 + //反向适配
  373 + this.$refs.tree.setCheckedKeys(this.permIds);
  374 + });
324 }, 375 },
325 //显示新增界面,每次点开初始化数据 376 //显示新增界面,每次点开初始化数据
326 - handleAdd: function () { 377 + handleAdd: function (index,row) {
327 this.addFormVisible = true; 378 this.addFormVisible = true;
328 this.addForm = { 379 this.addForm = {
329 - username: '',  
330 - password: '',  
331 - sex: 1,  
332 - address: '',  
333 - realname: '',  
334 - email: '',  
335 - mobilephone: '',  
336 - age: 1  
337 - };  
338 - this.getdepartmentNames(); 380 + description: '',
  381 + roleName: '',
  382 + roleSign: 1,
  383 + departmentId:'',
  384 + type: '',
  385 + businessLicense: '',
  386 + customsRegCode: '',
  387 + parentid: 0
  388 +
  389 + };
  390 + //如果新增下级
  391 + if(util.checkNull(row)){
  392 + //传递上级ID
  393 + let parentRole = Object.assign({}, row);
  394 + this.addForm.parentid = parentRole.roleId;
  395 + this.addForm.parentName = parentRole.roleName;
  396 + }
  397 +
  398 +// this.getdepartmentNames();
339 }, 399 },
340 //编辑 400 //编辑
341 editSubmit: function () { 401 editSubmit: function () {
@@ -406,7 +466,7 @@ @@ -406,7 +466,7 @@
406 //NProgress.start(); 466 //NProgress.start();
407 let role = Object.assign({}, this.permForm); 467 let role = Object.assign({}, this.permForm);
408 let roleId = role.roleId; 468 let roleId = role.roleId;
409 - let permissionIds = this.permIds 469 + let permissionIds = this.$refs.tree.getCheckedKeys();
410 let para = {roleId,permissionIds}; 470 let para = {roleId,permissionIds};
411 updateRolePerm(para).then((res) => { 471 updateRolePerm(para).then((res) => {
412 this.addLoading = false; 472 this.addLoading = false;
@@ -449,6 +509,81 @@ @@ -449,6 +509,81 @@
449 }).catch(() => { 509 }).catch(() => {
450 510
451 }); 511 });
  512 + },
  513 + treeHandleCheckChange: function (data, checked, indeterminate) {
  514 + if(checked) {
  515 + this.permIds.push(data.permissionId);
  516 + }else {
  517 + this.permIds.splice(this.permIds.contains(data.permissionId),1);
  518 + }
  519 + console.log(data, checked, indeterminate);
  520 +
  521 + },
  522 + uniteParentSame(id,treeStatus){//当子节点全为未选中时父节点也变为未选中状态
  523 + let node = this.$refs.tree.getNode(permissionId);//获取当前节点的节点树
  524 + if (node.parent !== null && node.parent !== undefined) {
  525 + let parentNode = node.parent.data;//获取当前节点的父节点树
  526 + if (parentNode != undefined){//判断父节点是否存在
  527 + for (let i = 0; i < parentNode.children.length; i++) {
  528 + let checkedKeys = this.$refs.tree.getCheckedKeys();
  529 + let hafCheckedKeys = this.$refs.tree.getHalfCheckedKeys();
  530 + let selectNodes = checkedKeys.concat(hafCheckedKeys);//获取已选择树节点
  531 + let selected = selectNodes.indexOf(parentNode.children[i].permissionId); // -1当前节点的同级节点是否全部未选中
  532 + if (selected !== -1){
  533 + return;
  534 + }
  535 + }
  536 + }else {
  537 + return;
  538 + }
  539 + this.$refs.tree.setChecked(parentNode.permissionId, false);//修改节点为未选择
  540 + if(node.level>2){//判断是否是最上级节点
  541 + this.uniteParentSame(parentNode.permissionId,treeStatus)
  542 + }
  543 + }else {
  544 + return;
  545 + }
  546 + },
  547 +
  548 + // 统一处理子节点为相同的勾选状态
  549 + uniteChildSame(treeList, isSelected){
  550 + this.$refs.tree.setChecked(treeList.permissionId, isSelected);
  551 + if (treeList.children !== undefined){
  552 + for (let i = 0; i < treeList.children.length; i++) {
  553 + this.uniteChildSame(treeList.children[i], isSelected)
  554 + }
  555 + }
  556 + },
  557 + // 统一处理父节点为选中
  558 + selectedParent(currentObj){
  559 + let currentNode = this.$refs.tree.getNode(currentObj);
  560 + if (currentNode.parent.key !== undefined) {
  561 + this.$refs.tree.setChecked(currentNode.parent, true);
  562 + this.selectedParent(currentNode.parent)
  563 + }
  564 + },
  565 + clickDeal: function (currentObj, treeStatus){
  566 + // 用于:父子节点严格互不关联时,父节点勾选变化时通知子节点同步变化,实现单向关联。
  567 + let selected = treeStatus.checkedKeys.indexOf(currentObj.permissionId); // -1未选中
  568 + // 选中
  569 + if (selected !== -1) {
  570 + // 子节点只要被选中父节点就被选中
  571 + this.selectedParent(currentObj);
  572 + // 统一处理子节点为相同的勾选状态
  573 + this.uniteChildSame(currentObj, true)
  574 + } else {
  575 + // 未选中 处理子节点全部未选中
  576 + if (currentObj.children !== undefined){
  577 + if (currentObj.children.length !== 0) {
  578 + this.uniteChildSame(currentObj, false)
  579 + }
  580 + //放开时为当子节点全为未选中时父节点也变为未选中状态 注释后就是父节点不和子节点强制绑定
  581 + // this.uniteParentSame(currentObj.id,treeStatus)//当子节点全为未选中时父节点也变为未选中状态
  582 + }
  583 + // else {
  584 + // this.uniteParentSame(currentObj.id,treeStatus)
  585 + // }
  586 + }
452 } 587 }
453 }, 588 },
454 mounted() { 589 mounted() {