组织机构

This commit is contained in:
吕金泽 2022-01-09 22:13:45 +08:00
parent 02cd4e7986
commit 33f76b8803
16 changed files with 759 additions and 150 deletions

View File

@ -0,0 +1,10 @@
{
"properties" : { },
"id" : "8295fc13678d4144bf7363c465247a50",
"name" : "组织机构",
"type" : "1",
"parentId" : "02df51e4d7184780a98b632f43dc5848",
"path" : "/office",
"paths" : [ ],
"options" : [ ]
}

View File

@ -0,0 +1,45 @@
{
"properties" : { },
"id" : "37aaae0a84ce4e00ad4f89d704d3cb51",
"script" : null,
"groupId" : "8295fc13678d4144bf7363c465247a50",
"name" : "上移",
"createTime" : null,
"updateTime" : 1641732205207,
"lock" : "0",
"method" : "GET",
"path" : "/sort/up",
"parameters" : [ ],
"option" : "[]",
"requestBody" : "",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : { }
}
================================
var top = db.selectOne("""
SELECT
id,
sort
FROM
sys_office
WHERE
is_del = 0
AND pid = #{pid}
AND sort < ( SELECT sort FROM sys_office WHERE is_del = 0 AND id = #{id} )
ORDER BY
sort DESC
LIMIT 1
""")
if(top){
db.update("""
update sys_office set sort = #{top.sort} where id = #{id}
""")
db.update("""
update sys_office set sort = #{sort} where id = #{top.id}
""")
}

View File

@ -0,0 +1,45 @@
{
"properties" : { },
"id" : "5f8edf5b8045475f92049270bcf0739a",
"script" : null,
"groupId" : "8295fc13678d4144bf7363c465247a50",
"name" : "下移",
"createTime" : null,
"updateTime" : 1641737498723,
"lock" : "0",
"method" : "GET",
"path" : "/sort/down",
"parameters" : [ ],
"option" : "[]",
"requestBody" : "",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : { }
}
================================
var top = db.selectOne("""
SELECT
id,
sort
FROM
sys_office
WHERE
is_del = 0
AND pid = #{pid}
AND sort > ( SELECT sort FROM sys_office WHERE is_del = 0 AND id = #{id} )
ORDER BY
sort
LIMIT 1
""")
if(top){
db.update("""
update sys_office set sort = #{top.sort} where id = #{id}
""")
db.update("""
update sys_office set sort = #{sort} where id = #{top.id}
""")
}

View File

@ -0,0 +1,26 @@
{
"properties" : { },
"id" : "03c2c9614e5b47f48f61f4f7759fe353",
"script" : null,
"groupId" : "8295fc13678d4144bf7363c465247a50",
"name" : "保存",
"createTime" : null,
"updateTime" : 1641732020139,
"lock" : "0",
"method" : "POST",
"path" : "/save",
"parameters" : [ ],
"option" : "[{\"name\":\"wrap_request_parameter\",\"value\":\"data\",\"description\":\"包装请求参数到一个变量中\"}]",
"requestBody" : "{}",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : {
"wrap_request_parameter" : "data"
}
}
================================
return db.table("sys_office").primary("id").saveOrUpdate(data);

View File

@ -0,0 +1,30 @@
{
"properties" : { },
"id" : "f7fa03a5d8b64dbaa39387c185a21adb",
"script" : null,
"groupId" : "8295fc13678d4144bf7363c465247a50",
"name" : "列表",
"createTime" : null,
"updateTime" : 1641731964401,
"lock" : "0",
"method" : "GET",
"path" : "/tree",
"parameters" : [ ],
"option" : "[]",
"requestBody" : "",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : { }
}
================================
var toTree = (list,pid) => select t.*,toTree(list,t.id) children from list t where t.pid = pid
var list = toTree(db.select('select id,name,pid,type,sort,code from sys_office where is_del = 0 order by sort'),'0')
return {
list: list,
total: list.getLength()
}

View File

@ -0,0 +1,97 @@
{
"properties" : { },
"id" : "4f2140a0d177450da2f27e4569afb7b8",
"script" : null,
"groupId" : "8295fc13678d4144bf7363c465247a50",
"name" : "删除",
"createTime" : null,
"updateTime" : 1641732068899,
"lock" : "0",
"method" : "POST",
"path" : "/delete",
"parameters" : [ ],
"option" : "[]",
"requestBody" : "{\r\n\t\r\n}",
"headers" : [ ],
"paths" : [ ],
"responseBody" : "{\n \"code\": 200,\n \"message\": \"success\",\n \"data\": null,\n \"timestamp\": 1641201245421,\n \"executeTime\": 7\n}",
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : {
"name" : "",
"value" : "",
"description" : "",
"required" : false,
"dataType" : "Object",
"type" : null,
"defaultValue" : null,
"validateType" : "",
"error" : "",
"expression" : "",
"children" : [ {
"name" : "code",
"value" : "200",
"description" : "",
"required" : false,
"dataType" : "Integer",
"type" : null,
"defaultValue" : null,
"validateType" : "",
"error" : "",
"expression" : "",
"children" : [ ]
}, {
"name" : "message",
"value" : "success",
"description" : "",
"required" : false,
"dataType" : "String",
"type" : null,
"defaultValue" : null,
"validateType" : "",
"error" : "",
"expression" : "",
"children" : [ ]
}, {
"name" : "data",
"value" : "null",
"description" : "",
"required" : false,
"dataType" : "Object",
"type" : null,
"defaultValue" : null,
"validateType" : "",
"error" : "",
"expression" : "",
"children" : [ ]
}, {
"name" : "timestamp",
"value" : "1641201245421",
"description" : "",
"required" : false,
"dataType" : "Long",
"type" : null,
"defaultValue" : null,
"validateType" : "",
"error" : "",
"expression" : "",
"children" : [ ]
}, {
"name" : "executeTime",
"value" : "7",
"description" : "",
"required" : false,
"dataType" : "Integer",
"type" : null,
"defaultValue" : null,
"validateType" : "",
"error" : "",
"expression" : "",
"children" : [ ]
} ]
},
"optionMap" : { }
}
================================
// db.table('sys_user_office').where().eq("office_id",id).delete();
return db.table("sys_office").logic().where().eq("id",id).delete();

View File

@ -0,0 +1,38 @@
{
"properties" : { },
"id" : "f6e998eaff2c49be807fcb38a1a7d55b",
"script" : null,
"groupId" : "8295fc13678d4144bf7363c465247a50",
"name" : "获取排序号",
"createTime" : null,
"updateTime" : 1641732159522,
"lock" : "0",
"method" : "GET",
"path" : "/sort",
"parameters" : [ {
"name" : "pid",
"value" : "",
"description" : "",
"required" : true,
"dataType" : "String",
"type" : null,
"defaultValue" : null,
"validateType" : null,
"error" : null,
"expression" : null,
"children" : null
} ],
"option" : "[]",
"requestBody" : "",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : { }
}
================================
return db.selectInt("""
select max(sort) + 10 from sys_office where pid = #{pid} and is_del = '0'
""") || 10;

View File

@ -0,0 +1,45 @@
{
"properties" : { },
"id" : "9817f2dbbc20419298e07bc644387f91",
"script" : null,
"groupId" : "67b2ce258e24491194b74992958c74aa",
"name" : "上移",
"createTime" : null,
"updateTime" : 1641564601649,
"lock" : "0",
"method" : "GET",
"path" : "/sort/up",
"parameters" : [ ],
"option" : "[]",
"requestBody" : "",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : { }
}
================================
var top = db.selectOne("""
SELECT
id,
sort
FROM
sys_menu
WHERE
is_del = 0
AND pid = #{pid}
AND sort < ( SELECT sort FROM sys_menu WHERE is_del = 0 AND id = #{id} )
ORDER BY
sort DESC
LIMIT 1
""")
if(top){
db.update("""
update sys_menu set sort = #{top.sort} where id = #{id}
""")
db.update("""
update sys_menu set sort = #{sort} where id = #{top.id}
""")
}

View File

@ -0,0 +1,45 @@
{
"properties" : { },
"id" : "77d393db826d4ba882b7c4b1d32e2e98",
"script" : null,
"groupId" : "67b2ce258e24491194b74992958c74aa",
"name" : "下移",
"createTime" : null,
"updateTime" : 1641564596885,
"lock" : "0",
"method" : "GET",
"path" : "/sort/down",
"parameters" : [ ],
"option" : "[]",
"requestBody" : "",
"headers" : [ ],
"paths" : [ ],
"responseBody" : null,
"description" : null,
"requestBodyDefinition" : null,
"responseBodyDefinition" : null,
"optionMap" : { }
}
================================
var top = db.selectOne("""
SELECT
id,
sort
FROM
sys_menu
WHERE
is_del = 0
AND pid = #{pid}
AND sort > ( SELECT sort FROM sys_menu WHERE is_del = 0 AND id = #{id} )
ORDER BY
sort
LIMIT 1
""")
if(top){
db.update("""
update sys_menu set sort = #{top.sort} where id = #{id}
""")
db.update("""
update sys_menu set sort = #{sort} where id = #{top.id}
""")
}

View File

@ -4,8 +4,8 @@
"script" : null,
"groupId" : "67b2ce258e24491194b74992958c74aa",
"name" : "获取排序号",
"createTime" : 1634724871167,
"updateTime" : 1634724871167,
"createTime" : null,
"updateTime" : 1641732167291,
"lock" : "0",
"method" : "GET",
"path" : "/sort",
@ -33,4 +33,6 @@
"optionMap" : { }
}
================================
return db.selectInt("""select max(sort) + 10 from sys_menu where pid = #{pid} and is_del = '0'""") || 10;
return db.selectInt("""
select max(sort) + 10 from sys_menu where pid = #{pid} and is_del = '0'
""") || 10;

View File

@ -23,7 +23,7 @@
/>
<div v-else-if="col.type == 'btns'">
<template v-for="btn in col.btns">
<el-button v-if="btn.if === undefined ? true : btn.if(scope.row)" :key="btn.title" v-permission="btn.permission" :type="btn.type" :size="btn.size || 'mini'" :class="btn.class" @click="btn.click(scope.row, scope.$index)">
<el-button v-if="btn.if === undefined ? true : btn.if(scope.row)" :icon="btn.icon" :key="btn.title" v-permission="btn.permission" :type="btn.type" :size="btn.size || 'mini'" :class="btn.class" @click="btn.click(scope.row, scope.$index)">
{{ btn.title }}
</el-button>
</template>

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1641720023979" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15481" width="240" height="240" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M960 1024h-320v-384h128V576H256v64h128v384H0v-384h128V448h320V384H320V0h384v384H576v64h320v192h128v384h-64zM128 896h128v-128H128v128zM576 128H448v128h128V128z m320 640h-128v128h128v-128z" p-id="15482"></path></svg>

After

Width:  |  Height:  |  Size: 592 B

View File

@ -22,6 +22,9 @@ Vue.use(elDragDialog)
import common from '@/scripts/common'
Vue.prototype.$common = common
import treeTable from '@/scripts/treeTable'
Vue.prototype.$treeTable = treeTable
import request from '@/scripts/request'
Vue.prototype.$request = request
Vue.prototype.$post = (url, data) => request.post(url, data, {

View File

@ -0,0 +1,82 @@
import common from "@/scripts/common";
const treeTable = {}
treeTable.isChildren = (children, id) => {
var result = false
for(var i in children) {
var chi = children[i]
if(chi.id == id){
result = true
}
if(chi.children && children.length > 0){
if(treeTable.isChildren(chi.children, id)){
result = true
}
}
}
return result
}
treeTable.queryChildren = (children, id) => {
var result = []
for(var i in children){
var chi = children[i]
if(chi.id == id){
if(chi.children && chi.children.length > 0){
result = chi.children
}
}else{
var qc = treeTable.queryChildren(chi.children, id)
if(qc.length > 0){
result = qc
}
}
}
return result
}
treeTable.genTree = (children) => {
var treeData = []
for(var i in children){
var chi = {}
chi.label = children[i].name
chi.id = children[i].id
if(children[i].children && children[i].children.length > 0){
chi.children = treeTable.genTree(children[i].children)
}
treeData.push(chi)
}
return treeData
}
treeTable.recursionSearch = (fields, data, text) => {
var searchData = []
for(var i in data){
var treeNode = data[i]
var children = treeNode.children
if(children && children.length > 0){
var childrenSearch = treeTable.recursionSearch(fields, children, text)
treeNode.children = childrenSearch && childrenSearch.length > 0 ? childrenSearch : treeNode.children
treeTable.treeNodeReplace(fields, searchData, treeNode, text, childrenSearch)
}else{
treeTable.treeNodeReplace(fields, searchData, treeNode, text)
}
}
return searchData
}
treeTable.treeNodeReplace = (fields, searchData, treeNode, text, childrenSearch) => {
var exist = false
fields.forEach((f) => {
if(treeNode[f] && treeNode[f].indexOf(text) != -1){
treeNode[f] = treeNode[f].replace(text, `<font color="#FAA353">${text}</font>`)
exist = true
}
})
if(exist || (childrenSearch && childrenSearch.length > 0)){
searchData.push(treeNode)
}
}
export default treeTable

View File

@ -1,3 +1,9 @@
<style>
.el-input-number .el-input__inner{
text-align: left;
}
</style>
<template>
<div class="app-container">
@ -19,17 +25,18 @@
<el-button class="filter-item" style="margin-bottom:10px;" type="primary" icon="el-icon-edit" @click="addSubMenu('0')">
添加菜单
</el-button>
<el-button type="primary" icon="el-icon-sort" plain @click="expand">展开/折叠</el-button>
</el-row>
<pd-table ref="table" v-bind="tableOptions" v-if="menuData && menuData.length > 0" />
<pd-table ref="table" v-bind="tableOptions" v-if="menuData && menuData.length > 0 && refreshTable" />
<pd-dialog ref="menuFormDialog" width="800px" :title="textMap[dialogStatus]" @confirm-click="save()">
<pd-dialog ref="menuFormDialog" width="1050px" :title="textMap[dialogStatus]" @confirm-click="save()">
<template #content>
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="right" label-width="80px" style="width: 600px; margin-left:50px;">
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="right" label-width="80px" style="width: 900px; margin-left:50px;">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="菜单类型" prop="type">
<el-radio-group v-model="temp.type" size="small">
<el-radio-group v-model="menuType" size="small">
<el-radio-button label="menu">菜单</el-radio-button>
<el-radio-button label="button">按钮</el-radio-button>
</el-radio-group>
@ -44,17 +51,22 @@
<el-form-item label="菜单名称" prop="name">
<el-input v-model="temp.name" />
</el-form-item>
<el-form-item label="菜单链接" prop="url" v-if="temp.type == 'menu'">
<el-form-item label="菜单链接" prop="url" v-if="menuType == 'menu'">
<el-input v-model="temp.url" />
</el-form-item>
<el-form-item label="权限标识" prop="permission">
<el-form-item label="权限标识" prop="permission" v-if="menuType == 'button'">
<el-input v-model="temp.permission" />
</el-form-item>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="图标" prop="icon" v-if="temp.type == 'menu'">
<el-col :span="6">
<el-form-item label="排序" prop="sort">
<el-input-number v-model="temp.sort" controls-position="right" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="选择图标" prop="icon" v-if="menuType == 'menu'">
<a @click="openIcons">
<el-input placeholder="请选择图标" v-model="temp.icon" class="input-with-select">
<el-input v-model="temp.icon" class="input-with-select">
<el-button class="icon-btn" slot="append">
<i v-html="generateIconCode(temp.icon)"></i>
</el-button>
@ -62,21 +74,20 @@
</a>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排序" prop="sort">
<el-input-number v-model="temp.sort" controls-position="right" />
<el-col :span="6">
<el-form-item label="菜单显示" v-if="menuType == 'menu'">
<el-radio-group v-model="temp.isShow" size="small">
<el-radio-button label="1">显示</el-radio-button>
<el-radio-button label="0">不显示</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="是否显示" v-if="temp.type == 'menu'">
<el-switch v-model="temp.isShow" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否缓存" v-if="temp.type == 'menu'">
<el-switch v-model="temp.keepAlive" :active-value="1" :inactive-value="0"></el-switch>
<el-col :span="6">
<el-form-item label="路由缓存" v-if="menuType == 'menu'">
<el-radio-group v-model="temp.keepAlive" size="small">
<el-radio-button label="1">缓存</el-radio-button>
<el-radio-button label="0">不缓存</el-radio-button>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
@ -102,6 +113,8 @@ export default {
components: { MenuIcons, Treeselect },
data() {
return {
menuType: 'menu',
refreshTable: true,
menuData: [],
menuTree: [],
searchValue: '',
@ -144,9 +157,44 @@ export default {
},
{
field: 'sort',
title: '序',
title: '',
width: 60
},
{
title: '排序',
type: 'btns',
width: 150,
btns: [
{
title: '上移',
type: 'text',
icon: 'el-icon-sort-up',
click: (row) => {
this.$get('menu/sort/up',{
id: row.id,
pid: row.pid,
sort: row.sort
}).then(() => {
this.reloadTable()
})
}
},
{
title: '下移',
type: 'text',
icon: 'el-icon-sort-down',
click: (row) => {
this.$get('menu/sort/down',{
id: row.id,
pid: row.pid,
sort: row.sort
}).then(() => {
this.reloadTable()
})
}
}
]
},
{
field: 'isShow',
title: '是否显示',
@ -174,13 +222,14 @@ export default {
{
title: '操作',
type: 'btns',
width: 262,
width: 260,
fixed: 'right',
align: 'left',
btns: [
{
title: '添加下级菜单',
type: 'text',
icon: 'el-icon-plus',
click: (row) => {
this.addSubMenu(row.id)
}
@ -188,6 +237,7 @@ export default {
{
title: '编辑',
type: 'text',
icon: 'el-icon-edit',
click: (row) => {
this.handleUpdate(row)
}
@ -195,6 +245,7 @@ export default {
{
title: '删除',
type: 'text',
icon: 'el-icon-delete',
click: (row) => {
this.$common.handleDelete({
url: 'menu/delete',
@ -227,7 +278,7 @@ export default {
this.reloadTable()
},
watch: {
'temp.type'(type) {
menuType(type) {
for (var t in this.getTemp()) {
if(t != 'type'){
this.temp[t] = row[t]
@ -243,95 +294,29 @@ export default {
this.menuTree = [{
label: '根节点',
id: '0',
children: this.genMenuTree(this.menuData)
children: this.$treeTable.genMenuTree(this.menuData)
}]
}
},
methods: {
isChildren(children, id) {
var result = false
for(var i in children) {
var chi = children[i]
if(chi.id == id){
result = true
}
if(chi.children && children.length > 0){
if(this.isChildren(chi.children, id)){
result = true
}
}
}
return result
},
queryChildren(children, id) {
var result = []
for(var i in children){
var chi = children[i]
if(chi.id == id){
if(chi.children && chi.children.length > 0){
result = chi.children
}
}else{
var qc = this.queryChildren(chi.children, id)
if(qc.length > 0){
result = qc
}
}
}
return result
},
genMenuTree(children) {
var menuTree = []
for(var i in children){
var chi = {}
chi.label = children[i].name
chi.id = children[i].id
if(children[i].children && children[i].children.length > 0){
chi.children = this.genMenuTree(children[i].children)
}
menuTree.push(chi)
}
return menuTree
expand(){
this.refreshTable = false
this.tableOptions.el["default-expand-all"] = !this.tableOptions.el["default-expand-all"]
this.$nextTick(() => {
this.refreshTable = true
})
},
searchMenu() {
var _this = this
clearTimeout(this.searchTimeout)
this.searchTimeout = setTimeout(() => {
if(_this.searchValue){
_this.$set(_this.tableOptions, 'data', _this.recursionSearch(_this.$common.copyNew(_this.menuData), _this.searchValue))
_this.$set(_this.tableOptions, 'data', _this.$treeTable.recursionSearch(['name', 'url', 'permission'], _this.$common.copyNew(_this.menuData), _this.searchValue))
}else{
_this.$set(_this.tableOptions, 'data', _this.menuData)
}
},1000)
},
recursionSearch(data, text){
var searchData = []
for(var i in data){
var treeNode = data[i]
var children = treeNode.children
if(children && children.length > 0){
var childrenSearch = this.recursionSearch(children, text)
treeNode.children = childrenSearch && childrenSearch.length > 0 ? childrenSearch : treeNode.children
this.treeNodeReplace(searchData, treeNode, text, childrenSearch)
}else{
this.treeNodeReplace(searchData, treeNode, text)
}
}
return searchData
},
treeNodeReplace(searchData, treeNode, text, childrenSearch){
var exist = false
var fields = ['name', 'url', 'permission']
fields.forEach((f) => {
if(treeNode[f] && treeNode[f].indexOf(text) != -1){
treeNode[f] = treeNode[f].replace(text, `<font color="#FAA353">${text}</font>`)
exist = true
}
})
if(exist || (childrenSearch && childrenSearch.length > 0)){
searchData.push(treeNode)
}
},
generateIconCode(symbol) {
return `<svg style="width: 20px;height: 20px;fill: #999" aria-hidden="true" class="svg-icon disabled"><use href="#icon-${symbol}"></use></svg>`
},
@ -353,7 +338,6 @@ export default {
isShow: 1,
pid: '',
icon: '',
type: 'menu',
keepAlive: 1
}
},
@ -388,7 +372,7 @@ export default {
})
return
}
if(this.isChildren(this.queryChildren(this.menuData, this.temp.id), this.temp.pid)){
if(this.$treeTable.isChildren(this.$treeTable.queryChildren(this.menuData, this.temp.id), this.temp.pid)){
this.$notify({
title: '失败',
message: '上级菜单不能选当前菜单子级',
@ -397,6 +381,14 @@ export default {
})
return
}
if(this.menuType == 'menu'){
this.temp.permission = ''
}else{
this.temp.isShow = 1
this.temp.keepAlive = 1
this.temp.icon = ''
this.temp.url = ''
}
this.$post('menu/save', this.temp).then(() => {
this.reloadTable()
this.$refs.menuFormDialog.hide()
@ -420,7 +412,7 @@ export default {
for (var t in this.temp) {
this.temp[t] = row[t]
}
this.temp.type = this.temp.url ? 'menu' : 'button'
this.menuType = this.temp.url ? 'menu' : 'button'
this.temp.name = this.temp.name.replaceAll(/<font.*?>(.*?)<\/font>/g,'$1')
this.dialogStatus = 'update'
this.$refs.menuFormDialog.show()

View File

@ -1,24 +1,69 @@
<style>
.el-input-number .el-input__inner{
text-align: left;
}
</style>
<template>
<div class="app-container">
<el-button class="filter-item" style="margin-bottom:10px;" type="primary" icon="el-icon-edit" @click="addSubMenu('0')">
添加组织机构
</el-button>
<div class="filter-container">
<el-form :inline="true">
<el-form-item label="机构搜索">
<el-input v-model="searchValue" @input="searchOffice" placeholder="机构名称、链接、权限标识" style="width: 200px"></el-input>
</el-form-item>
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="searchOffice">
搜索
</el-button>
<el-button class="filter-item" icon="el-icon-delete" @click="() => { this.searchValue = ''; searchOffice() }">
清空
</el-button>
</el-form>
</div>
<pd-table ref="table" v-bind="tableOptions" />
<el-row style="margin-bottom: 5px">
<el-button class="filter-item" style="margin-bottom:10px;" type="primary" icon="el-icon-edit" @click="addSubOffice('0')">
添加机构
</el-button>
<el-button type="primary" icon="el-icon-sort" plain @click="expand">展开/折叠</el-button>
</el-row>
<pd-dialog :visible.sync="dialogFormVisible" width="600px" @confirm-click="$refs.dataForm.save()">
<pd-table ref="table" v-bind="tableOptions" v-if="officeData && officeData.length > 0 && refreshTable" />
<pd-dialog ref="officeFormDialog" width="1050px" :title="textMap[dialogStatus]" @confirm-click="save()">
<template #content>
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="100px" style="width: 400px; margin-left:50px;">
<el-form-item label="名称" prop="name">
<el-input v-model="temp.name" />
</el-form-item>
<el-form-item label="类型" prop="type">
<pd-select v-model="temp.type" type="office_type" width="100%" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="temp.sort" />
</el-form-item>
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="right" label-width="80px" style="width: 900px; margin-left:50px;">
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="机构类型" prop="type">
<pd-select v-model="temp.type" type="office_type" width="100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="上级机构" prop="pid">
<treeselect v-model="temp.pid" :options="officeTree" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="12">
<el-form-item label="机构名称" prop="name">
<el-input v-model="temp.name" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="机构编码" prop="code">
<el-input v-model="temp.code" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="6">
<el-form-item label="排序" prop="sort">
<el-input-number v-model="temp.sort" controls-position="right" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
</pd-dialog>
@ -27,61 +72,106 @@
</template>
<script>
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {
components: { Treeselect },
data() {
return {
refreshTable: true,
officeData: [],
officeTree: [],
searchValue: '',
tableOptions: {
el: {
'default-expand-all': true,
'tree-props': { children: 'children' },
'tree-props': { children: 'children', hasChildren: 'hasChildren' },
'row-key': 'id'
},
showNo: false,
data: [],
updateStr: '',
page: false,
cols: [
{
field: 'name',
title: '名称',
width: '400',
align: 'left'
title: '机构名称',
align: 'left',
type: 'html'
},
{
field: 'type',
title: '类型',
dictType: 'office_type',
width: '250',
align: 'left'
field: 'code',
title: '机构编码',
width: 300,
align: 'left',
type: 'html'
},
{
field: 'sort',
title: '序',
title: '',
width: 60
},
{
title: '排序',
type: 'btns',
width: 150,
btns: [
{
title: '上移',
type: 'text',
icon: 'el-icon-sort-up',
click: (row) => {
this.$get('office/sort/up',{
id: row.id,
pid: row.pid,
sort: row.sort
}).then(() => {
this.reloadTable()
})
}
},
{
title: '下移',
type: 'text',
icon: 'el-icon-sort-down',
click: (row) => {
this.$get('office/sort/down',{
id: row.id,
pid: row.pid,
sort: row.sort
}).then(() => {
this.reloadTable()
})
}
}
]
},
{
title: '操作',
type: 'btns',
width: 260,
fixed: 'right',
align: 'left',
btns: [
{
title: '添加下级',
type: 'primary',
title: '添加下级机构',
type: 'text',
icon: 'el-icon-plus',
click: (row) => {
this.addSubMenu(row.id)
this.addSubOffice(row.id)
}
},
{
title: '编辑',
type: 'primary',
type: 'text',
icon: 'el-icon-edit',
click: (row) => {
this.handleUpdate(row)
}
},
{
title: '删除',
type: 'danger',
type: 'text',
icon: 'el-icon-delete',
click: (row) => {
this.$common.handleDelete({
url: 'office/delete',
@ -101,33 +191,71 @@ export default {
create: '添加'
},
temp: this.getTemp(),
listConfigDialogVisible: false,
formConfigDialogVisible: false,
rules: {
name: [{ required: true, message: '请输入名称', trigger: 'change' }],
type: [{ required: true, message: '请选择类型', trigger: 'change' }]
}
pid: [{ required: true, message: '请选择上级机构', trigger: 'change' }],
name: [{ required: true, message: '请输入机构名称', trigger: 'change' }]
},
searchTimeout: ''
}
},
created() {
mounted() {
this.reloadTable()
},
watch: {
officeData() {
this.officeTree = [{
label: '根节点',
id: '0',
children: this.$treeTable.genTree(this.officeData)
}]
}
},
methods: {
expand(){
this.refreshTable = false
this.tableOptions.el["default-expand-all"] = !this.tableOptions.el["default-expand-all"]
this.$nextTick(() => {
this.refreshTable = true
})
},
searchOffice() {
var _this = this
clearTimeout(this.searchTimeout)
this.searchTimeout = setTimeout(() => {
if(_this.searchValue){
_this.$set(_this.tableOptions, 'data', _this.$treeTable.recursionSearch(['name', 'code'], _this.$common.copyNew(_this.officeData), _this.searchValue))
}else{
_this.$set(_this.tableOptions, 'data', _this.officeData)
}
},1000)
},
getTemp() {
return {
id: '',
name: '',
type: '',
sort: 0,
pid: ''
pid: '',
type: '',
code: ''
}
},
resetTemp() {
this.temp = this.getTemp()
},
addSubMenu(id) {
getSort() {
this.$get('office/sort', { pid: this.temp.pid }).then(res => {
this.temp.sort = res.data
})
},
addSubOffice(id) {
this.resetTemp()
this.temp.pid = id
this.temp.id = this.$common.uuid()
this.getSort()
this.dialogStatus = 'create'
this.dialogFormVisible = true
this.$refs.officeFormDialog.show()
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
@ -135,9 +263,27 @@ export default {
save() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
if(this.temp.pid == this.temp.id){
this.$notify({
title: '失败',
message: '上级机构不能选当前机构',
type: 'error',
duration: 2000
})
return
}
if(this.$treeTable.isChildren(this.$treeTable.queryChildren(this.officeData, this.temp.id), this.temp.pid)){
this.$notify({
title: '失败',
message: '上级机构不能选当前机构子级',
type: 'error',
duration: 2000
})
return
}
this.$post('office/save', this.temp).then(() => {
this.reloadTable()
this.dialogFormVisible = false
this.$refs.officeFormDialog.hide()
this.$notify({
title: '成功',
message: (this.dialogStatus === 'create' ? '创建' : '修改') + '成功',
@ -149,16 +295,18 @@ export default {
})
},
reloadTable() {
this.$get('office/list').then(res => {
this.$set(this.tableOptions, 'data', this.$common.handlerTreeData(res.data, 'id', 'pid', 'sort', '0'))
this.$get('office/tree').then(res => {
this.officeData = res.data.list
this.$set(this.tableOptions, 'data', this.officeData)
})
},
handleUpdate(row) {
for (var t in this.temp) {
this.temp[t] = row[t]
}
this.temp.name = this.temp.name.replaceAll(/<font.*?>(.*?)<\/font>/g,'$1')
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.$refs.officeFormDialog.show()
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})