xiongzhu пре 4 година
родитељ
комит
64bdcdc18b

+ 73 - 58
src/main/data-center-admin/src/views/Admin.vue

@@ -38,7 +38,11 @@
                 </el-tooltip>
                 </el-tooltip>
 
 
                 <el-dropdown @command="onCommand" style="margin-left: 20px" trigger="click">
                 <el-dropdown @command="onCommand" style="margin-left: 20px" trigger="click">
-                    <img :src="userInfo ? userInfo.avatar || '' : ''" class="avatar" />
+                    <div style="display: flex; align-items: center; padding-right: 20px; cursor: pointer">
+                        <img :src="userInfo ? userInfo.avatar || '' : ''" class="avatar" />{{
+                            (userInfo || {}).nickname
+                        }}
+                    </div>
                     <el-dropdown-menu slot="dropdown">
                     <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item command="pwd" style="word-break: keep-all">修改密码 </el-dropdown-item>
                         <el-dropdown-item command="pwd" style="word-break: keep-all">修改密码 </el-dropdown-item>
                         <el-dropdown-item command="logout">退出登录 </el-dropdown-item>
                         <el-dropdown-item command="logout">退出登录 </el-dropdown-item>
@@ -230,65 +234,76 @@ export default {
             };
             };
             findActiveMenu([], this.rawMenus);
             findActiveMenu([], this.rawMenus);
         },
         },
+        // getMenus() {
+        //     let menus = [
+        //         { active: false, name: '数据可视化', path: '/chart1', icon: 'fas fa-globe-asia' },
+        //         { active: false, name: '描述性统计', path: '/chart2', icon: 'fas fa-chart-line' },
+        //         { active: false, name: '数据分析', path: '/chart3', icon: 'fas fa-chart-area' },
+        //         {
+        //             active: false,
+        //             name: '系统管理',
+        //             icon: 'fas fa-cog',
+        //             children: [
+        //                 { active: false, name: '日志管理', path: '/operationLogList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '配置管理', path: '/sysConfigList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '存储管理', path: '/genCodeList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '用户管理', path: '/userList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '角色管理', path: '/authorityList', icon: 'fas fa-bars' }
+        //             ]
+        //         },
+        //         {
+        //             active: false,
+        //             name: '数据编辑',
+        //             icon: 'fas fa-bars',
+        //             children: [
+        //                 { active: false, name: '系统模块', path: '/categoryList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '数据总览', path: '/summaryStateList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '数据表名', path: '/summaryTypeList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '检测规则', path: '/thresholdList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '企业数量', path: '/orgNumStatList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '项目数量', path: '/projectNumStatList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '城市指数', path: '/cityIndexStatList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '基地分布', path: '/baseStatList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '技术交易', path: '/techTradeStatList', icon: 'fas fa-bars' }
+        //             ]
+        //         },
+        //         {
+        //             active: false,
+        //             name: '指标体系管理',
+        //             icon: 'fas fa-bars',
+        //             children: [
+        //                 { active: false, name: '指标列表', path: '/metricList', icon: 'fas fa-bars' },
+        //                 { active: false, name: '指标编辑', path: '/metricEdit', icon: 'fas fa-bars' }
+        //             ]
+        //         }
+        //     ];
+        //     function setId(parentId, menus) {
+        //         menus.forEach((i, idx) => {
+        //             if (parentId) {
+        //                 i.id = parentId * 10000 + idx + 1;
+        //             } else {
+        //                 i.id = idx + 1;
+        //             }
+        //             if (i.children) {
+        //                 setId(i.id, i.children);
+        //             }
+        //         });
+        //     }
+        //     setId('', menus);
+        //     this.rawMenus = menus;
+        //     this.menus = menus;
+        //     this.findActiveMenu();
+        // },
         getMenus() {
         getMenus() {
-            let menus = [
-                { active: false, name: '数据可视化', path: '/chart1', icon: 'fas fa-globe-asia' },
-                { active: false, name: '描述性统计', path: '/chart2', icon: 'fas fa-chart-line' },
-                { active: false, name: '数据分析', path: '/chart3', icon: 'fas fa-chart-area' },
-                {
-                    active: false,
-                    name: '系统管理',
-                    icon: 'fas fa-cog',
-                    children: [
-                        { active: false, name: '日志管理', path: '/operationLogList', icon: 'fas fa-bars' },
-                        { active: false, name: '配置管理', path: '/sysConfigList', icon: 'fas fa-bars' },
-                        { active: false, name: '存储管理', path: '/genCodeList', icon: 'fas fa-bars' },
-                        { active: false, name: '用户管理', path: '/userList', icon: 'fas fa-bars' },
-                        { active: false, name: '角色管理', path: '/authorityList', icon: 'fas fa-bars' }
-                    ]
-                },
-                {
-                    active: false,
-                    name: '数据编辑',
-                    icon: 'fas fa-bars',
-                    children: [
-                        { active: false, name: '系统模块', path: '/categoryList', icon: 'fas fa-bars' },
-                        { active: false, name: '数据总览', path: '/summaryStateList', icon: 'fas fa-bars' },
-                        { active: false, name: '数据表名', path: '/summaryTypeList', icon: 'fas fa-bars' },
-                        { active: false, name: '检测规则', path: '/thresholdList', icon: 'fas fa-bars' },
-                        { active: false, name: '企业数量', path: '/orgNumStatList', icon: 'fas fa-bars' },
-                        { active: false, name: '项目数量', path: '/projectNumStatList', icon: 'fas fa-bars' },
-                        { active: false, name: '城市指数', path: '/cityIndexStatList', icon: 'fas fa-bars' },
-                        { active: false, name: '基地分布', path: '/baseStatList', icon: 'fas fa-bars' },
-                        { active: false, name: '技术交易', path: '/techTradeStatList', icon: 'fas fa-bars' }
-                    ]
-                },
-                {
-                    active: false,
-                    name: '指标体系管理',
-                    icon: 'fas fa-bars',
-                    children: [
-                        { active: false, name: '指标列表', path: '/metricList', icon: 'fas fa-bars' },
-                        { active: false, name: '指标编辑', path: '/metricEdit', icon: 'fas fa-bars' }
-                    ]
-                }
-            ];
-            function setId(parentId, menus) {
-                menus.forEach((i, idx) => {
-                    if (parentId) {
-                        i.id = parentId * 10000 + idx + 1;
-                    } else {
-                        i.id = idx + 1;
-                    }
-                    if (i.children) {
-                        setId(i.id, i.children);
-                    }
+            this.$http
+                .get('/dataCenterMenu/userMenu', {
+                    name: '系统菜单'
+                })
+                .then(res => {
+                    this.rawMenus = res;
+                    this.menus = res;
+                    this.findActiveMenu();
                 });
                 });
-            }
-            setId('', menus);
-            this.rawMenus = menus;
-            this.menus = menus;
-            this.findActiveMenu();
         },
         },
         toggleFullScreen() {
         toggleFullScreen() {
             this.isFullscreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;
             this.isFullscreen = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen;

+ 3 - 4
src/main/data-center-admin/src/views/AuthorityEdit.vue

@@ -20,7 +20,6 @@
             </el-form-item>
             </el-form-item>
             <el-form-item>
             <el-form-item>
                 <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
                 <el-button @click="onSave" :loading="saving" type="primary">保存</el-button>
-                <el-button @click="onDelete" :loading="saving" type="danger" v-if="formData.id">删除 </el-button>
                 <el-button @click="$router.go(-1)">取消</el-button>
                 <el-button @click="$router.go(-1)">取消</el-button>
             </el-form-item>
             </el-form-item>
         </el-form>
         </el-form>
@@ -32,7 +31,7 @@ export default {
     created() {
     created() {
         if (this.$route.query.id) {
         if (this.$route.query.id) {
             this.$http
             this.$http
-                .get('authority/get/' + this.$route.query.id)
+                .get('/dataCenterAuthority/get/' + this.$route.query.id)
                 .then(res => {
                 .then(res => {
                     this.formData = res;
                     this.formData = res;
                 })
                 })
@@ -79,7 +78,7 @@ export default {
 
 
             this.saving = true;
             this.saving = true;
             this.$http
             this.$http
-                .post('/authority/save', data, { body: 'json' })
+                .post('/dataCenterAuthority/save', data, { body: 'json' })
                 .then(res => {
                 .then(res => {
                     this.saving = false;
                     this.saving = false;
                     this.$message.success('成功');
                     this.$message.success('成功');
@@ -94,7 +93,7 @@ export default {
         onDelete() {
         onDelete() {
             this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
             this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
                 .then(() => {
                 .then(() => {
-                    return this.$http.post(`/authority/del/${this.formData.id}`);
+                    return this.$http.post(`/dataCenterAuthority/del/${this.formData.name}`);
                 })
                 })
                 .then(() => {
                 .then(() => {
                     this.$message.success('删除成功');
                     this.$message.success('删除成功');

+ 3 - 3
src/main/data-center-admin/src/views/AuthorityList.vue

@@ -62,7 +62,7 @@
 <script>
 <script>
 import { mapState } from 'vuex';
 import { mapState } from 'vuex';
 import pageableTable from '@/mixins/pageableTable';
 import pageableTable from '@/mixins/pageableTable';
-import userMenu from './editUserMenu';
+import userMenu from './editDataCenterMenu';
 export default {
 export default {
     name: 'AuthorityList',
     name: 'AuthorityList',
     mixins: [pageableTable],
     mixins: [pageableTable],
@@ -73,7 +73,7 @@ export default {
         return {
         return {
             multipleMode: false,
             multipleMode: false,
             search: '',
             search: '',
-            url: '/authority/all',
+            url: '/dataCenterAuthority/all',
             downloading: false,
             downloading: false,
             editMenu: {
             editMenu: {
                 title: '',
                 title: '',
@@ -164,7 +164,7 @@ export default {
         deleteRow(row) {
         deleteRow(row) {
             this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
             this.$alert('删除将无法恢复,确认要删除么?', '警告', { type: 'error' })
                 .then(() => {
                 .then(() => {
-                    return this.$http.post(`/authority/del/${row.id}`);
+                    return this.$http.post(`/dataCenterAuthority/del/${row.name}`);
                 })
                 })
                 .then(() => {
                 .then(() => {
                     this.$message.success('删除成功');
                     this.$message.success('删除成功');

+ 119 - 205
src/main/data-center-admin/src/views/Menus.vue

@@ -1,96 +1,56 @@
 <template>
 <template>
-    <div class="menus">
-        <el-select v-model="category" placeholder="分类" clearable>
-            <el-option v-for="item in categories" :label="item" :key="item" :value="item"></el-option>
-        </el-select>
-        <el-row :gutter="20">
-            <el-col :span="12">
-                <div class="menu-tree">
-                    <el-tree
-                        :data="menus"
-                        :render-content="renderContent"
-                        :highlight-current="true"
-                        :expand-on-click-node="true"
-                        node-key="id"
-                        v-loading="loading"
-                        accordion
-                        @node-click="nodeClick"
-                        :default-expanded-keys="expandKeys"
-                        :default-checked-keys="expandKeys"
+    <div class="edit-view" style="padding:20px;">
+        <el-tree
+            :data="menus"
+            :render-content="renderContent"
+            :highlight-current="true"
+            :expand-on-click-node="true"
+            node-key="id"
+            default-expand-all
+            v-loading="loading"
+        >
+        </el-tree>
+        <el-button type="text" @click="addRootMenu" style="margin-left: 24px;">添加 </el-button>
+        <el-dialog :visible.sync="dialogVisible" title="添加菜单">
+            <el-form :model="menu" ref="form" label-position="top">
+                <el-form-item
+                    label="菜单名"
+                    prop="name"
+                    :rules="[{ required: true, message: '请填写菜单名', trigger: 'blur' }]"
+                >
+                    <el-input v-model="menu.name"></el-input>
+                </el-form-item>
+                <el-form-item label="菜单地址" prop="path">
+                    <el-input v-model="menu.path"></el-input>
+                </el-form-item>
+                <el-form-item prop="icon">
+                    <template slot="label"
+                        >图标
+                        <a
+                            href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free"
+                            target="_blank"
+                            class="available-icons"
+                            >查看所有可用图标</a
+                        ></template
                     >
                     >
-                    </el-tree>
-                    <el-button type="text" @click="addRootMenu" style="margin-left: 24px;">添加 </el-button>
-                </div>
-            </el-col>
-            <transition name="el-fade-in">
-                <el-col :span="12" v-if="dialogVisible">
-                    <div class="menu-tree">
-                        <div style="font-weight:bold;padding:10px 0">{{ menu.id ? '编辑菜单' : '新增菜单' }}</div>
-                        <el-form :model="menu" ref="form" label-position="top">
-                            <el-form-item
-                                label="菜单名"
-                                prop="name"
-                                :rules="[{ required: true, message: '请填写菜单名', trigger: 'blur' }]"
-                            >
-                                <el-input v-model="menu.name"></el-input>
-                            </el-form-item>
-                            <el-form-item label="菜单地址" prop="path">
-                                <el-input v-model="menu.path"></el-input>
-                            </el-form-item>
-                            <el-form-item prop="icon">
-                                <template slot="label"
-                                    >图标
-                                    <a
-                                        href="https://fontawesome.com/icons?d=gallery&s=brands,solid&m=free"
-                                        target="_blank"
-                                        class="available-icons"
-                                        >查看所有可用图标</a
-                                    ></template
-                                >
-                                <el-input v-model="icon">
-                                    <template slot="append"
-                                        ><span ref="iconContainer" style="font-size: 18px;"
-                                            ><i class="fas fa-"></i></span
-                                    ></template>
-                                </el-input>
-                            </el-form-item>
-                            <el-form-item prop="category" label="分类" v-if="menu.root">
-                                <el-input v-model="menu.category"></el-input>
-                            </el-form-item>
-                            <el-form-item prop="authorities" label="权限">
-                                <el-select
-                                    v-model="menu.authorities"
-                                    clearable
-                                    multiple
-                                    value-key="name"
-                                    style="width:100%"
-                                >
-                                    <el-option
-                                        v-for="item in authorities"
-                                        :label="item.description"
-                                        :value="item"
-                                        :key="item.name"
-                                    ></el-option>
-                                </el-select>
-                            </el-form-item>
-                        </el-form>
-                        <div slot="footer">
-                            <el-button @click="dialogVisible = false">取消 </el-button>
-                            <el-button type="primary" @click="addMenu" :loading="loading">保存 </el-button>
-                        </div>
-                    </div>
-                </el-col>
-            </transition>
-        </el-row>
+                    <el-input v-model="icon">
+                        <template slot="append"
+                            ><span ref="iconContainer" style="font-size: 18px;"><i class="fas fa-"></i></span
+                        ></template>
+                    </el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer">
+                <el-button @click="dialogVisible = false">取消 </el-button>
+                <el-button type="primary" @click="addMenu" :loading="loading">保存 </el-button>
+            </div>
+        </el-dialog>
     </div>
     </div>
 </template>
 </template>
 <script>
 <script>
 export default {
 export default {
     created() {
     created() {
         this.getData();
         this.getData();
-        this.$http.get('/authority/all').then(res => {
-            this.authorities = res;
-        });
     },
     },
     data() {
     data() {
         return {
         return {
@@ -108,11 +68,7 @@ export default {
             parent: null,
             parent: null,
             currentRef: null,
             currentRef: null,
             edit: false,
             edit: false,
-            icon: '',
-            categories: [],
-            category: null,
-            expandKeys: [],
-            authorities: []
+            icon: ''
         };
         };
     },
     },
     methods: {
     methods: {
@@ -122,9 +78,7 @@ export default {
                 path: '',
                 path: '',
                 active: true,
                 active: true,
                 root: true,
                 root: true,
-                icon: 'bars',
-                category: this.category || null,
-                authorities: [{ name: 'ROLE_ADMIN' }]
+                icon: 'bars'
             };
             };
             this.parent = null;
             this.parent = null;
             this.icon = 'bars';
             this.icon = 'bars';
@@ -142,8 +96,7 @@ export default {
                 path: '',
                 path: '',
                 active: true,
                 active: true,
                 root: false,
                 root: false,
-                icon: null,
-                authorities: [{ name: 'ROLE_ADMIN' }]
+                icon: null
             };
             };
             this.icon = '';
             this.icon = '';
             this.dialogVisible = true;
             this.dialogVisible = true;
@@ -181,12 +134,22 @@ export default {
                     let menu = { ...this.menu };
                     let menu = { ...this.menu };
                     delete menu.children;
                     delete menu.children;
                     this.$http
                     this.$http
-                        .post('/menu/save', menu, { body: 'json' })
+                        .post('/dataCenterMenu/save', menu)
                         .then(res => {
                         .then(res => {
                             this.loading = false;
                             this.loading = false;
                             this.$message.success('添加成功');
                             this.$message.success('添加成功');
                             this.dialogVisible = false;
                             this.dialogVisible = false;
-                            this.getData();
+                            if (this.edit) {
+                                for (let [key, value] of Object.entries(res)) {
+                                    console.log(`${key}: ${value}`);
+                                    this.$set(this.currentRef, key, value);
+                                }
+                            } else if (this.parent) {
+                                this.parent.children = this.parent.children || [];
+                                this.parent.children.push(res);
+                            } else {
+                                this.menus.push(res);
+                            }
                         })
                         })
                         .catch(e => {
                         .catch(e => {
                             console.log(e);
                             console.log(e);
@@ -204,27 +167,29 @@ export default {
                 type: 'error'
                 type: 'error'
             })
             })
                 .then(() => {
                 .then(() => {
-                    return this.$http.post(
-                        '/menu/save',
-                        {
+                    this.$http
+                        .post('/dataCenterMenu/save', {
                             ...data,
                             ...data,
                             active: false,
                             active: false,
+                            enabled: false,
                             children: null
                             children: null
-                        },
-                        { body: 'json' }
-                    );
-                })
-                .then(res => {
-                    this.$message.success('删除成功');
-                    this.getData();
+                        })
+                        .then(res => {
+                            this.$message.success('删除成功');
+                            let index = node.parent.data.children.findIndex(i => {
+                                return i.id === data.id;
+                            });
+                            if (index > -1) {
+                                node.parent.data.children.splice(index, 1);
+                            }
+                        })
+                        .catch(e => {
+                            console.log(e);
+                            this.loading = false;
+                            this.$message.error(e.error);
+                        });
                 })
                 })
-                .catch(e => {
-                    this.loading = false;
-                    if (e !== 'cancel') {
-                        console.log(e);
-                        this.$message.error(e.error);
-                    }
-                });
+                .catch(() => {});
         },
         },
         moveUp(node, data) {
         moveUp(node, data) {
             if (node.previousSibling) {
             if (node.previousSibling) {
@@ -232,28 +197,25 @@ export default {
                 let sort0 = node.previousSibling.data.sort,
                 let sort0 = node.previousSibling.data.sort,
                     sort1 = node.data.sort;
                     sort1 = node.data.sort;
                 Promise.all([
                 Promise.all([
-                    this.$http.post(
-                        '/menu/save',
-                        {
-                            ...node.data,
-                            children: null,
-                            sort: sort0
-                        },
-                        { body: 'json' }
-                    ),
-                    this.$http.post(
-                        '/menu/save',
-                        {
-                            ...node.previousSibling.data,
-                            children: null,
-                            sort: sort1
-                        },
-                        { body: 'json' }
-                    )
+                    this.$http.post('/dataCenterMenu/save', {
+                        ...node.data,
+                        children: null,
+                        sort: sort0
+                    }),
+                    this.$http.post('/dataCenterMenu/save', {
+                        ...node.previousSibling.data,
+                        children: null,
+                        sort: sort1
+                    })
                 ])
                 ])
                     .then(_ => {
                     .then(_ => {
                         this.loading = false;
                         this.loading = false;
-                        this.getData();
+                        let tmp = { ...node.previousSibling.data, sort: sort1 };
+                        node.previousSibling.data = {
+                            ...node.data,
+                            sort: sort0
+                        };
+                        node.data = tmp;
                     })
                     })
                     .catch(e => {
                     .catch(e => {
                         console.log(e);
                         console.log(e);
@@ -268,28 +230,22 @@ export default {
                 let sort0 = node.data.sort,
                 let sort0 = node.data.sort,
                     sort1 = node.nextSibling.data.sort;
                     sort1 = node.nextSibling.data.sort;
                 Promise.all([
                 Promise.all([
-                    this.$http.post(
-                        '/menu/save',
-                        {
-                            ...node.data,
-                            children: null,
-                            sort: sort1
-                        },
-                        { body: 'json' }
-                    ),
-                    this.$http.post(
-                        '/menu/save',
-                        {
-                            ...node.nextSibling.data,
-                            children: null,
-                            sort: sort0
-                        },
-                        { body: 'json' }
-                    )
+                    this.$http.post('/dataCenterMenu/save', {
+                        ...node.data,
+                        children: null,
+                        sort: sort1
+                    }),
+                    this.$http.post('/dataCenterMenu/save', {
+                        ...node.nextSibling.data,
+                        children: null,
+                        sort: sort0
+                    })
                 ])
                 ])
                     .then(_ => {
                     .then(_ => {
                         this.loading = false;
                         this.loading = false;
-                        this.getData();
+                        let tmp = { ...node.nextSibling.data, sort: sort0 };
+                        node.nextSibling.data = { ...node.data, sort: sort1 };
+                        node.data = tmp;
                     })
                     })
                     .catch(e => {
                     .catch(e => {
                         console.log(e);
                         console.log(e);
@@ -300,7 +256,7 @@ export default {
         },
         },
         getData() {
         getData() {
             this.$http
             this.$http
-                .get('/menu/all', { category: this.category })
+                .get('/dataCenterMenu/all')
                 .then(res => {
                 .then(res => {
                     this.menus = res;
                     this.menus = res;
                 })
                 })
@@ -308,19 +264,10 @@ export default {
                     console.log(e);
                     console.log(e);
                     this.$message.error(e.error);
                     this.$message.error(e.error);
                 });
                 });
-            this.$http.get('/menu/categories').then(res => {
-                this.categories = res;
-            });
         },
         },
         renderContent(h, { node, data, store }) {
         renderContent(h, { node, data, store }) {
             return (
             return (
-                <span
-                    class={
-                        this.menu.id == data.id || (this.menu.parent == data.id && !this.menu.id)
-                            ? 'custom-tree-node selected'
-                            : 'custom-tree-node'
-                    }
-                >
+                <span class="custom-tree-node">
                     <span>{data.name}</span>
                     <span>{data.name}</span>
                     <span class="url">{data.path}</span>
                     <span class="url">{data.path}</span>
                     <span class="opt">
                     <span class="opt">
@@ -398,42 +345,23 @@ export default {
                 FontAwesome.dom.i2svg();
                 FontAwesome.dom.i2svg();
                 this.menu.icon = '';
                 this.menu.icon = '';
             }
             }
-        },
-        nodeClick(data, node, el) {
-            if (this.expandKeys[0] != data.id) {
-                this.expandKeys = [data.id];
-            }
         }
         }
     },
     },
     watch: {
     watch: {
         icon(val) {
         icon(val) {
             this.showIcon(val);
             this.showIcon(val);
-        },
-        category() {
-            this.getData();
         }
         }
     }
     }
 };
 };
 </script>
 </script>
-<style lang="less" scoped>
-.menus {
-    padding: 20px;
-}
-.menu-tree {
-    border-radius: 4px;
-    background: white;
-    margin-top: 20px;
-    padding: 10px;
-}
-/deep/ .custom-tree-node {
+<style lang="less">
+.custom-tree-node {
     flex: 1;
     flex: 1;
     display: flex;
     display: flex;
     align-items: center;
     align-items: center;
     justify-content: space-between;
     justify-content: space-between;
     font-size: 14px;
     font-size: 14px;
     padding-right: 8px;
     padding-right: 8px;
-    line-height: 40px;
-    height: 40px;
     .url {
     .url {
         flex-grow: 1;
         flex-grow: 1;
         text-align: right;
         text-align: right;
@@ -443,33 +371,19 @@ export default {
     .opt {
     .opt {
         opacity: 0;
         opacity: 0;
     }
     }
-    &.selected {
-        border: 2px solid @prim;
-        border-radius: 4px;
-        padding: 0 10px;
-        box-sizing: border-box;
-        .opt {
-            opacity: 1;
-        }
-    }
-    &:hover {
-        .opt {
-            opacity: 1;
-        }
-    }
 }
 }
-/deep/ .menu-tree {
-    .el-tree-node__content {
-        height: 40px;
-        line-height: 40px;
+
+.custom-tree-node:hover {
+    .opt {
+        opacity: 1;
     }
     }
 }
 }
 
 
-/deep/ .available-icons {
-    color: @prim;
+.available-icons {
+    color: #409eff;
     text-decoration: none;
     text-decoration: none;
     &:hover {
     &:hover {
-        color: @prim;
+        color: #409eff;
         text-decoration: none;
         text-decoration: none;
     }
     }
 }
 }

+ 10 - 4
src/main/data-center-admin/src/views/UserEdit.vue

@@ -29,8 +29,14 @@
             <el-form-item prop="email" label="邮箱">
             <el-form-item prop="email" label="邮箱">
                 <el-input v-model="formData.email"></el-input>
                 <el-input v-model="formData.email"></el-input>
             </el-form-item>
             </el-form-item>
-            <el-form-item prop="authorities" label="角色">
-                <el-select v-model="formData.authorities" multiple placeholder="请选择" value-key="name">
+            <el-form-item prop="dataCenterAuthorities" label="角色">
+                <el-select
+                    v-model="formData.dataCenterAuthorities"
+                    multiple
+                    placeholder="请选择"
+                    value-key="name"
+                    :multiple-limit="1"
+                >
                     <el-option v-for="item in authorities" :key="item.name" :label="item.nameDesc" :value="item">
                     <el-option v-for="item in authorities" :key="item.name" :label="item.nameDesc" :value="item">
                     </el-option>
                     </el-option>
                 </el-select>
                 </el-select>
@@ -60,7 +66,7 @@ export default {
                 });
                 });
         }
         }
         this.$http
         this.$http
-            .get('/authority/all')
+            .get('/dataCenterAuthority/all')
             .then(res => {
             .then(res => {
                 this.authorities = res.content;
                 this.authorities = res.content;
             })
             })
@@ -100,7 +106,7 @@ export default {
                         trigger: 'blur'
                         trigger: 'blur'
                     }
                     }
                 ],
                 ],
-                authorities: [{ required: true, message: '请选择角色', trigger: 'blur' }],
+                dataCenterAuthorities: [{ required: true, message: '请选择角色', trigger: 'blur' }],
                 email: [
                 email: [
                     { required: true, message: '请输入邮箱', trigger: 'blur' },
                     { required: true, message: '请输入邮箱', trigger: 'blur' },
                     { type: 'email', message: '请输入正确的邮箱', trigger: 'blur' }
                     { type: 'email', message: '请输入正确的邮箱', trigger: 'blur' }

+ 116 - 0
src/main/data-center-admin/src/views/editDataCenterMenu.vue

@@ -0,0 +1,116 @@
+<template>
+    <el-dialog
+        id="userMenu"
+        width="30%"
+        :title="editMenu.title"
+        :visible.sync="editMenu.editDialogVisible"
+        append-to-body
+        :before-close="handleClose"
+        @open="open"
+        :close-on-click-modal="false"
+    >
+        <el-tree
+            :props="props1"
+            :show-checkbox="true"
+            default-expand-all
+            node-key="id"
+            ref="tree"
+            :data="menuList"
+            @check="handleCheckChange"
+            highlight-current
+            v-loading="loading"
+        >
+        </el-tree>
+        <div slot="footer" class="dialog-footer">
+            <el-button @click="handleClose" :disabled="saving">取 消</el-button>
+            <el-button type="primary" @click="handleSubmit" :loading="saving">确 定</el-button>
+        </div>
+    </el-dialog>
+</template>
+
+<script>
+export default {
+    name: 'userMenu',
+    props: ['editMenu'],
+    data: function() {
+        return {
+            loading: false,
+            menuList: [],
+            checkedId: [],
+            checkedTreeId: [],
+            props1: {
+                label: 'name',
+                children: 'children'
+            },
+            saving: false
+        };
+    },
+    components: {},
+    methods: {
+        open() {
+            this.queryMenu();
+        },
+        queryMenu() {
+            this.$http
+                .get('/dataCenterMenu/allUserMenu', { authorityName: this.editMenu.roleId })
+                .then(res => {
+                    this.checkedId = [];
+                    this.menuList = res.menuList;
+                    this.checkedId = res.menuId;
+                    if (this.checkedId != undefined && this.checkedId.length > 0) {
+                        this.setCheckedKeys(this.checkedId);
+                    }
+                    this.loading = false;
+                })
+                .catch(e => {
+                    this.loading = false;
+                    console.log(e);
+                    this.$message.error(e.error);
+                });
+        },
+        setCheckedKeys(ids) {
+            this.$refs.tree.setCheckedKeys(ids);
+        },
+        handleCheckChange(data, checked) {
+            this.checkedTreeId = this.$refs.tree.getCheckedKeys();
+        },
+        handleClose() {
+            this.$emit('closeEditMenu', false); // 给父组件传值,隐藏弹出框
+        },
+        handleSubmit() {
+            // 为该角色添加权限;
+            this.saving = true;
+            this.$http
+                .post(
+                    '/dataCenterAuthorityMenu/save',
+                    { authorityName: this.editMenu.roleId, menuId: this.checkedTreeId.join(',') },
+                    { body: 'json' }
+                )
+                .then(res => {
+                    console.log(res);
+                    this.saving = false;
+                    this.$message({
+                        type: 'success',
+                        message: '提交成功'
+                    });
+                    this.$emit('closeEditMenu', false); // 给父组件传值,隐藏弹出框
+                })
+                .catch(error => {
+                    this.saving = false;
+                    console.log(error);
+                    this.$message.error('服务器暂时无法连接,请稍后再试');
+                });
+        }
+    },
+    mounted: function() {
+        // this.$nextTick(function() {});
+    }
+};
+</script>
+
+<style>
+#userMenu .el-dialog__body {
+    overflow: auto;
+    max-height: 310px;
+}
+</style>

+ 21 - 0
src/main/java/com/izouma/jmrh/domain/DataCenterAuthorityMenu.java

@@ -0,0 +1,21 @@
+package com.izouma.jmrh.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.persistence.Entity;
+
+/**
+ * @Description  
+ * @Author  lh
+ * @Date 2020-12-27 18:46:05 
+ */
+
+@Entity
+@Data
+public class DataCenterAuthorityMenu extends BaseEntity{
+	@ApiModelProperty("菜单")
+	private String menuId;
+	@ApiModelProperty("角色")
+	private String authorityName;
+}

+ 41 - 0
src/main/java/com/izouma/jmrh/domain/DataCenterMenu.java

@@ -0,0 +1,41 @@
+package com.izouma.jmrh.domain;
+
+import lombok.Data;
+import org.hibernate.annotations.Where;
+
+import javax.persistence.Entity;
+import javax.persistence.Transient;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+@Entity
+@Where(clause = "active = 1")
+public class DataCenterMenu extends BaseEntity implements Serializable,Comparable {
+    private String name;
+
+    private String path;
+
+    private String icon;
+
+    private Integer sort;
+
+    private Long parent;
+
+    private Boolean root;
+
+    private Boolean enabled;
+
+    private Boolean active;
+
+    private String category;
+    @Transient
+    List<DataCenterMenu> children =new ArrayList<>();
+
+    @Override
+    public int compareTo(Object o) {
+        DataCenterMenu menu = (DataCenterMenu) o;
+        return this.getSort().compareTo(menu.getSort());
+    }
+}

+ 10 - 0
src/main/java/com/izouma/jmrh/domain/User.java

@@ -6,6 +6,7 @@ import com.izouma.jmrh.annotations.Searchable;
 import com.izouma.jmrh.config.Constants;
 import com.izouma.jmrh.config.Constants;
 import com.izouma.jmrh.converter.EncryptConverter;
 import com.izouma.jmrh.converter.EncryptConverter;
 import com.izouma.jmrh.security.Authority;
 import com.izouma.jmrh.security.Authority;
+import com.izouma.jmrh.security.DataCenterAuthority;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModel;
 import lombok.AllArgsConstructor;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Builder;
@@ -57,6 +58,15 @@ public class User extends BaseEntity implements Serializable {
     @ExcelIgnore
     @ExcelIgnore
     private Set<Authority> authorities = new HashSet<>();
     private Set<Authority> authorities = new HashSet<>();
 
 
+    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.DETACH})
+    @JoinTable(
+            name = "user_data_center_authority",
+            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))},
+            inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))})
+    @BatchSize(size = 20)
+    @ExcelIgnore
+    private Set<DataCenterAuthority> dataCenterAuthorities = new HashSet<>();
+
     private String openId;
     private String openId;
 
 
     private String sex;
     private String sex;

+ 19 - 0
src/main/java/com/izouma/jmrh/repo/DataCenterAuthorityMenuRepo.java

@@ -0,0 +1,19 @@
+package com.izouma.jmrh.repo;
+
+import com.izouma.jmrh.domain.AuthorityMenu;
+import com.izouma.jmrh.domain.DataCenterAuthorityMenu;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+
+import javax.transaction.Transactional;
+
+public interface DataCenterAuthorityMenuRepo extends JpaRepository<DataCenterAuthorityMenu, Long>, JpaSpecificationExecutor<DataCenterAuthorityMenu> {
+    DataCenterAuthorityMenu findByAuthorityName(String authorityName);
+
+    @Modifying
+    @Transactional
+    @Query(value = "update data_center_authority_menu set menu_id = ?1 where authority_name = ?2", nativeQuery = true)
+    Integer updateByAuthorityName(String menuIds, String name);
+}

+ 9 - 0
src/main/java/com/izouma/jmrh/repo/DataCenterAuthorityRepo.java

@@ -0,0 +1,9 @@
+package com.izouma.jmrh.repo;
+
+import com.izouma.jmrh.security.Authority;
+import com.izouma.jmrh.security.DataCenterAuthority;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+public interface DataCenterAuthorityRepo extends JpaRepository<DataCenterAuthority, String>, JpaSpecificationExecutor<DataCenterAuthority> {
+}

+ 32 - 0
src/main/java/com/izouma/jmrh/repo/DataCenterMenuRepo.java

@@ -0,0 +1,32 @@
+package com.izouma.jmrh.repo;
+
+import com.izouma.jmrh.domain.DataCenterMenu;
+import com.izouma.jmrh.domain.Menu;
+import org.hibernate.annotations.Where;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+public interface DataCenterMenuRepo extends JpaRepository<DataCenterMenu, Long>, JpaSpecificationExecutor<DataCenterMenu> {
+    List<DataCenterMenu> findByRootTrue();
+
+    @Where(clause = "enabled = 1")
+    List<DataCenterMenu> findByNameAndRootTrue(String name);
+
+    List<DataCenterMenu> findByEnabledTrue();
+
+    @Query(nativeQuery = true, value = "SELECT ifnull(max(sort + 1),1) FROM data_center_menu")
+    int nextSort();
+
+    @Query(value = "SELECT * FROM data_center_menu " +
+            "WHERE id in " +
+            "  (SELECT id FROM data_center_menu " +
+            "   WHERE FIND_IN_SET ( id, ?1 )  " +
+            "   AND enabled = 1 " +
+            "   UNION " +
+            "   SELECT DISTINCT (parent) id  FROM data_center_menu " +
+            "   WHERE FIND_IN_SET ( id, ?1 )  AND enabled = 1) AND enabled = 1 ", nativeQuery = true)
+    List<DataCenterMenu> findByInId(String Ids);
+}

+ 71 - 0
src/main/java/com/izouma/jmrh/security/DataCenterAuthority.java

@@ -0,0 +1,71 @@
+package com.izouma.jmrh.security;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.Objects;
+
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class DataCenterAuthority implements Serializable {
+    public enum NAMES {
+        ROLE_USER, ROLE_DEV, ROLE_ADMIN, ROLE_INTERACT, ROLE_NOTICE, ROLE_POLICY, ROLE_SUPPLY
+    }
+
+    @Id
+    @Size(max = 50)
+    @NotNull
+    @Column(length = 50)
+    private String name;
+
+
+    @ApiModelProperty(name = "名称")
+    private String nameDesc;
+
+    @ApiModelProperty(name = "描述")
+    private String description;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        DataCenterAuthority authority = (DataCenterAuthority) o;
+
+        return Objects.equals(name, authority.name);
+    }
+
+    @Override
+    public int hashCode() {
+        return name != null ? name.hashCode() : 0;
+    }
+
+    public DataCenterAuthority(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return "Authority{" +
+                "name='" + name + '\'' +
+                "}";
+    }
+}

+ 57 - 0
src/main/java/com/izouma/jmrh/web/DataCenterAuthorityController.java

@@ -0,0 +1,57 @@
+package com.izouma.jmrh.web;
+
+import com.izouma.jmrh.domain.ExceptionLog;
+import com.izouma.jmrh.dto.PageQuery;
+import com.izouma.jmrh.exception.BusinessException;
+import com.izouma.jmrh.repo.AuthorityRepo;
+import com.izouma.jmrh.repo.DataCenterAuthorityRepo;
+import com.izouma.jmrh.security.Authority;
+import com.izouma.jmrh.security.DataCenterAuthority;
+import com.izouma.jmrh.service.AuthorityService;
+import com.izouma.jmrh.utils.ObjUtils;
+import com.izouma.jmrh.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+@RestController
+@RequestMapping("/dataCenterAuthority")
+@AllArgsConstructor
+public class DataCenterAuthorityController extends BaseController {
+    private DataCenterAuthorityRepo authorityRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public DataCenterAuthority save(@RequestBody DataCenterAuthority record) {
+        return authorityRepo.save(record);
+    }
+
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/all")
+    public Page<DataCenterAuthority> all(PageQuery pageQuery) {
+        return authorityRepo.findAll(toSpecification(pageQuery, DataCenterAuthority.class), toPageRequest(pageQuery));
+    }
+
+    @GetMapping("/get/{id}")
+    public DataCenterAuthority get(@PathVariable String id) {
+        return authorityRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable String id) {
+        authorityRepo.deleteById(id);
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<DataCenterAuthority> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 69 - 0
src/main/java/com/izouma/jmrh/web/DataCenterAuthorityMenuController.java

@@ -0,0 +1,69 @@
+package com.izouma.jmrh.web;
+
+import com.izouma.jmrh.domain.DataCenterAuthorityMenu;
+import com.izouma.jmrh.dto.PageQuery;
+import com.izouma.jmrh.exception.BusinessException;
+import com.izouma.jmrh.repo.DataCenterAuthorityMenuRepo;
+import com.izouma.jmrh.repo.DataCenterMenuRepo;
+import com.izouma.jmrh.utils.excel.ExcelUtils;
+import lombok.AllArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/dataCenterAuthorityMenu")
+@AllArgsConstructor
+public class DataCenterAuthorityMenuController extends BaseController {
+
+    private DataCenterAuthorityMenuRepo authorityMenuRepo;
+    private DataCenterMenuRepo          dataCenterMenuRepo;
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public Map save(@RequestBody DataCenterAuthorityMenu record) {
+        HashMap<String, Object> rest = new HashMap<>();
+        rest.put("success", false);
+        if (record != null) {
+            DataCenterAuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(record.getAuthorityName());
+            if (byAuthorityName == null) {
+                if (authorityMenuRepo.save(record) != null)
+                    rest.put("success", true);
+            }
+            if (authorityMenuRepo.updateByAuthorityName(record.getMenuId(), record.getAuthorityName()) > 0) {
+                rest.put("success", true);
+            }
+        }
+        return rest;
+    }
+
+    //@PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/all")
+    public Page<DataCenterAuthorityMenu> all(PageQuery pageQuery) {
+        return authorityMenuRepo.findAll(toSpecification(pageQuery, DataCenterAuthorityMenu.class), toPageRequest(pageQuery));
+    }
+
+    @GetMapping("/get/{id}")
+    public DataCenterAuthorityMenu get(@PathVariable Long id) {
+        return authorityMenuRepo.findById(id).orElseThrow(new BusinessException("无记录"));
+    }
+
+    @PostMapping("/del/{id}")
+    public void del(@PathVariable Long id) {
+        authorityMenuRepo.deleteById(id);
+
+    }
+
+    @GetMapping("/excel")
+    @ResponseBody
+    public void excel(HttpServletResponse response, PageQuery pageQuery) throws IOException {
+        List<DataCenterAuthorityMenu> data = all(pageQuery).getContent();
+        ExcelUtils.export(response, data);
+    }
+}
+

+ 163 - 0
src/main/java/com/izouma/jmrh/web/DataCenterMenuController.java

@@ -0,0 +1,163 @@
+package com.izouma.jmrh.web;
+
+import com.alibaba.fastjson.JSONArray;
+import com.izouma.jmrh.domain.DataCenterAuthorityMenu;
+import com.izouma.jmrh.domain.DataCenterMenu;
+import com.izouma.jmrh.repo.DataCenterAuthorityMenuRepo;
+import com.izouma.jmrh.repo.DataCenterMenuRepo;
+import com.izouma.jmrh.security.DataCenterAuthority;
+import com.izouma.jmrh.utils.SecurityUtils;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.io.Resource;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/dataCenterMenu")
+public class DataCenterMenuController extends BaseController {
+    @Autowired
+    private DataCenterMenuRepo          menuRepo;
+    @Autowired
+    private DataCenterAuthorityMenuRepo authorityMenuRepo;
+    @Value("classpath:/static/backlog.json")
+    private Resource                    resource;
+
+    /*
+    * 登录角色权限菜单
+    * */
+    @GetMapping("/userMenu")
+    public List<DataCenterMenu> userMenu() {
+        Set<DataCenterAuthority> authorities = SecurityUtils.getAuthenticatedUser().getDataCenterAuthorities();
+        String menuIds = "";
+        for (DataCenterAuthority item : authorities) {
+            DataCenterAuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(item.getName());
+            if (byAuthorityName != null) {
+                if (byAuthorityName.getMenuId() != null && byAuthorityName.getMenuId() != "") {
+                    menuIds += "," + byAuthorityName.getMenuId();
+                }
+            }
+        }
+        String substring = menuIds.substring(1);
+        List<DataCenterMenu> menuList = menuRepo.findByInId(substring);
+        //List<Menu> menuList = menuRepo.findByNameAndRootTrue(name);
+      /*  for (Menu menu : menuList) {
+            sortMenu(menu);
+        }*/
+        List<DataCenterMenu> child = getChild(12542L, menuList);
+        Collections.sort(child);
+        return child;
+    }
+
+    /*
+     * 待办列表菜单
+     * */
+    @GetMapping("/userMenuList")
+    public List<Map<String, String>> userMenuList() {
+        Set<DataCenterAuthority> authorities = SecurityUtils.getAuthenticatedUser().getDataCenterAuthorities();
+        String menuIds = "";
+        for (DataCenterAuthority item : authorities) {
+            DataCenterAuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(item.getName());
+            if (byAuthorityName != null) {
+                if (byAuthorityName.getMenuId() != null && byAuthorityName.getMenuId() != "") {
+                    menuIds += "," + byAuthorityName.getMenuId();
+                }
+            }
+        }
+        String substring = menuIds.substring(1);
+        List<DataCenterMenu> menuList = menuRepo.findByInId(substring);
+        List<Map<String, String>> hashMaps = new ArrayList<>();
+        try {
+            String areaData = IOUtils.toString(resource.getInputStream(), Charset.forName("UTF-8"));
+            List<Map<String, String>> list = JSONArray.parseObject(areaData, List.class);
+            for (DataCenterMenu menu : menuList) {
+                for (Map<String, String> map : list) {
+                    if (menu.getPath().equals(map.get("url"))) {
+                        String url = menu.getPath().substring(0, menu.getPath().indexOf("List"));
+                        map.put("listAll", url + "/all");
+                        map.put("countUrl", url + "/count");
+                        hashMaps.add(map);
+                    }
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return hashMaps;
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/all")
+    public List<DataCenterMenu> all() {
+        List<DataCenterMenu> menuList = menuRepo.findByEnabledTrue();
+        //menuList.forEach(this::sortMenu);
+        return getChild(0L, menuList);
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/allUserMenu")
+    public Map allUserMenu(String authorityName) {
+        List<DataCenterMenu> menuList = menuRepo.findByEnabledTrue();
+        DataCenterAuthorityMenu byAuthorityName = authorityMenuRepo.findByAuthorityName(authorityName);
+        HashMap mode = new HashMap<String, Objects>();
+        mode.put("menuList", getChild(0L, menuList));
+        if (byAuthorityName != null) {
+            String menuId = byAuthorityName.getMenuId();
+            String[] split = menuId.split(",");
+            mode.put("menuId", split);
+        }
+        return mode;
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @PostMapping("/save")
+    public DataCenterMenu save(DataCenterMenu menu) {
+        if (menu.getEnabled() == null) {
+            menu.setEnabled(true);
+        }
+        if (menu.getSort() == null) {
+            menu.setSort(menuRepo.nextSort());
+        }
+        menuRepo.save(menu);
+        return menu;
+    }
+
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping("/groupByCategory")
+    public Map<String, List<DataCenterMenu>> groupByCategory() {
+        return menuRepo.findAll().stream()
+                .filter(menu -> menu.getCategory() != null)
+                .collect(Collectors.groupingBy(DataCenterMenu::getCategory));
+    }
+
+    private void sortMenu(DataCenterMenu menu) {
+        if (menu.getChildren() != null) {
+            menu.getChildren().sort(Comparator.comparingInt(DataCenterMenu::getSort));
+        }
+        menu.getChildren().forEach(this::sortMenu);
+    }
+
+    private static List<DataCenterMenu> getChild(Long pid, List<DataCenterMenu> allList) {
+        ArrayList<DataCenterMenu> child = new ArrayList<>();
+        for (DataCenterMenu menu : allList) {
+            if (pid.longValue() == menu.getParent().longValue()) {
+                menu.setChildren(getChild(menu.getId(), allList));
+                if (menu.getChildren().size() > 0) {
+                    Collections.sort(menu.getChildren());
+                    /*menu.getChildren().sort(Comparator.comparingInt(Menu::getSort));*/
+                }
+                child.add(menu);
+            }
+        }
+        return child;
+    }
+}

+ 6 - 1
src/main/vue/src/views/Admin.vue

@@ -98,7 +98,11 @@
                 </el-tooltip>
                 </el-tooltip>
 
 
                 <el-dropdown @command="onCommand" style="margin-left: 20px">
                 <el-dropdown @command="onCommand" style="margin-left: 20px">
-                    <img :src="userInfo ? userInfo.avatar || '' : ''" class="avatar" />
+                    <div style="display: flex; align-items: center; padding-right: 20px; cursor: pointer">
+                        <img :src="userInfo ? userInfo.avatar || '' : ''" class="avatar" />{{
+                            (userInfo || {}).nickname
+                        }}
+                    </div>
                     <el-dropdown-menu slot="dropdown">
                     <el-dropdown-menu slot="dropdown">
                         <el-dropdown-item command="pwd" style="word-break: keep-all">修改密码 </el-dropdown-item>
                         <el-dropdown-item command="pwd" style="word-break: keep-all">修改密码 </el-dropdown-item>
                         <el-dropdown-item command="logout">退出登录 </el-dropdown-item>
                         <el-dropdown-item command="logout">退出登录 </el-dropdown-item>
@@ -554,6 +558,7 @@ export default {
     .avatar {
     .avatar {
         width: 40px;
         width: 40px;
         height: 40px;
         height: 40px;
+        margin-right: 20px;
         border-radius: 50%;
         border-radius: 50%;
     }
     }
     a {
     a {