Przeglądaj źródła

动态menu和角色关联以及基础menu构建

pixelqm 5 lat temu
rodzic
commit
8a8fa3b880

+ 107 - 1
QMPlusServer/controller/api/menu.go

@@ -6,6 +6,7 @@ import (
 	"main/controller/servers"
 	"main/middleware"
 	"main/model/dbModel"
+	"main/model/modelInterface"
 )
 
 // @Tags Menu
@@ -15,7 +16,6 @@ import (
 // @Param data body api.RegistAndLoginStuct true "可以什么都不填"
 // @Success 200 {string} json "{"success":true,"data":{},"msg":"返回成功"}"
 // @Router /menu/getMenu [post]
-
 func GetMenu(c *gin.Context) {
 	claims, _ := c.Get("claims")
 	waitUse := claims.(*middleware.CustomClaims)
@@ -26,3 +26,109 @@ func GetMenu(c *gin.Context) {
 		servers.ReportFormat(c, true, "获取成功", gin.H{"menus": menus})
 	}
 }
+
+// @Tags authority
+// @Summary 分页获取基础menu列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.PageInfo true "分页获取基础menu列表"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /menu/getMenuList [post]
+func GetMenuList(c *gin.Context) {
+	var pageInfo modelInterface.PageInfo
+	_ = c.BindJSON(&pageInfo)
+	err, menuList, total := new(dbModel.BaseMenu).GetInfoList(pageInfo)
+	if err != nil {
+		servers.ReportFormat(c, false, fmt.Sprintf("获取数据失败,%v", err), gin.H{})
+	} else {
+		servers.ReportFormat(c, true, "获取数据成功", gin.H{
+			"menuList": menuList,
+			"total":    total,
+			"page":     pageInfo.Page,
+			"pageSize": pageInfo.PageSize,
+		})
+	}
+}
+
+// @Tags authority
+// @Summary 分页获取基础menu列表
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.PageInfo true "分页获取基础menu列表"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /menu/addBaseMenu [post]
+func AddBaseMenu(c *gin.Context) {
+	var addMenu dbModel.BaseMenu
+	_ = c.BindJSON(&addMenu)
+	err := addMenu.AddBaseMenu()
+	if err != nil {
+		servers.ReportFormat(c, false, fmt.Sprintf("添加失败,%v", err), gin.H{})
+	} else {
+		servers.ReportFormat(c, true, fmt.Sprintf("添加成功,%v", err), gin.H{})
+	}
+}
+
+// @Tags Menu
+// @Summary 获取用户动态路由
+// @Security ApiKeyAuth
+// @Produce  application/json
+// @Param data body api.RegistAndLoginStuct true "可以什么都不填"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"返回成功"}"
+// @Router /menu/getBaseMenuTree [post]
+func GetBaseMenuTree(c *gin.Context) {
+	err, menus := new(dbModel.BaseMenu).GetBaseMenuTree()
+	if err != nil {
+		servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{"menus": menus})
+	} else {
+		servers.ReportFormat(c, true, "获取成功", gin.H{"menus": menus})
+	}
+}
+
+type AddMenuAuthorityInfo struct {
+	Menus       []dbModel.BaseMenu
+	AuthorityId string
+}
+
+// @Tags authority
+// @Summary 增加menu和角色关联关系
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.AddMenuAuthorityInfo true "增加menu和角色关联关系"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /menu/addMenuAuthority [post]
+func AddMenuAuthority(c *gin.Context) {
+	var addMenuAuthorityInfo AddMenuAuthorityInfo
+	_ = c.BindJSON(&addMenuAuthorityInfo)
+	err := new(dbModel.Menu).AddMenuAuthority(addMenuAuthorityInfo.Menus, addMenuAuthorityInfo.AuthorityId)
+	if err != nil {
+		servers.ReportFormat(c, false, fmt.Sprintf("添加失败,%v", err), gin.H{})
+	} else {
+		servers.ReportFormat(c, true, fmt.Sprintf("添加成功,%v", err), gin.H{})
+	}
+}
+
+type AuthorityIdInfo struct {
+	AuthorityId string
+}
+
+// @Tags authority
+// @Summary 获取指定角色menu
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Param data body modelInterface.AuthorityIdInfo true "增加menu和角色关联关系"
+// @Success 200 {string} json "{"success":true,"data":{},"msg":"获取成功"}"
+// @Router /menu/addMenuAuthority [post]
+func GetMenuAuthority(c *gin.Context) {
+	var authorityIdInfo AuthorityIdInfo
+	_ = c.BindJSON(&authorityIdInfo)
+	err, menus := new(dbModel.Menu).GetMenuAuthority(authorityIdInfo.AuthorityId)
+	if err != nil {
+		servers.ReportFormat(c, false, fmt.Sprintf("获取失败:%v", err), gin.H{"menus": menus})
+	} else {
+		servers.ReportFormat(c, true, "获取成功", gin.H{"menus": menus})
+	}
+}

+ 1 - 1
QMPlusServer/init/registTable/registTable.go

@@ -7,5 +7,5 @@ import (
 
 //注册数据库表专用
 func RegistTable(db *gorm.DB) {
-	db.AutoMigrate(dbModel.User{}, dbModel.Authority{}, dbModel.Menu{}, dbModel.Api{})
+	db.AutoMigrate(dbModel.User{}, dbModel.Authority{}, dbModel.Menu{}, dbModel.Api{}, dbModel.ApiAuthority{}, dbModel.BaseMenu{})
 }

+ 8 - 4
QMPlusServer/model/dbModel/api.go

@@ -9,23 +9,27 @@ import (
 
 type Api struct {
 	gorm.Model  `json:"-"`
-	AuthorityId uint   `json:"-"`
 	Path        string `json:"path"`
 	Description string `json:"description"`
 }
 
 func (a *Api) CreateApi() (err error) {
-	err = qmsql.DEFAULTDB.Create(a).Error
+	findOne := qmsql.DEFAULTDB.Where("path = ?", a.Path).Find(&Menu{}).Error
+	if findOne != nil {
+
+	} else {
+		err = qmsql.DEFAULTDB.Create(a).Error
+	}
 	return err
 }
 
 func (a *Api) DeleteApi() (err error) {
-	err = qmsql.DEFAULTDB.Where("id = ?", a.AuthorityId).Delete(a).Error
+	err = qmsql.DEFAULTDB.Where("path = ?", a.Path).Delete(a).Delete(&ApiAuthority{}).Error
 	return err
 }
 
 func (a *Api) EditApi() (err error) {
-	err = qmsql.DEFAULTDB.Update(a).Error
+	err = qmsql.DEFAULTDB.Update(a).Update(&Authority{}).Error
 	return err
 }
 

+ 6 - 0
QMPlusServer/model/dbModel/api_authority.go

@@ -0,0 +1,6 @@
+package dbModel
+
+type ApiAuthority struct {
+	AuthorityId string `json:"-"`
+	Api
+}

+ 55 - 0
QMPlusServer/model/dbModel/baseMenu.go

@@ -0,0 +1,55 @@
+package dbModel
+
+import (
+	"github.com/jinzhu/gorm"
+	"github.com/pkg/errors"
+	"main/controller/servers"
+	"main/init/qmsql"
+	"main/model/modelInterface"
+)
+
+type BaseMenu struct {
+	gorm.Model
+	MenuLevel uint   `json:"-"`
+	ParentId  string `json:"parentId"`
+	Path      string `json:"path"`
+	Name      string `json:"name"`
+	Hidden    bool   `json:"hidden"`
+	Component string `json:"component"`
+	Meta      `json:"meta"`
+	NickName  string     `json:"nickName"`
+	Children  []BaseMenu `json:"children"`
+}
+
+func (b *BaseMenu) AddBaseMenu() (err error) {
+	findOne := qmsql.DEFAULTDB.Where("name = ?", b.Name).Find(&BaseMenu{}).Error
+	if findOne != nil {
+		b.NickName = b.Title
+		err = qmsql.DEFAULTDB.Create(b).Error
+	} else {
+		err = errors.New("存在重复name,请修改name")
+	}
+	return err
+}
+
+func (b *BaseMenu) DeleteBaseMenu(name string) (err error) {
+	err = qmsql.DEFAULTDB.Where("name = ?", name).Delete(&b).Delete(&Menu{}).Error
+	return err
+}
+
+func (b *BaseMenu) UpdataBaseMenu(name string) (err error) {
+	err = qmsql.DEFAULTDB.Where("name = ?", name).Update(&b).Update(&Menu{}).Error
+	return err
+}
+
+func (b *BaseMenu) GetInfoList(info modelInterface.PageInfo) (err error, list interface{}, total int) {
+	// 封装分页方法 调用即可 传入 当前的结构体和分页信息
+	err, db, total := servers.PagingServer(b, info)
+	if err != nil {
+		return
+	} else {
+		var menuList []BaseMenu
+		err = db.Find(&menuList).Error
+		return err, menuList, total
+	}
+}

+ 0 - 41
QMPlusServer/model/dbModel/menu.go

@@ -1,41 +0,0 @@
-package dbModel
-
-import (
-	"github.com/jinzhu/gorm"
-	"main/init/qmsql"
-)
-
-type Menu struct {
-	gorm.Model  `json:"-"`
-	MenuLevel   uint   `json:"-"`
-	AuthorityId uint   `json:"-"`
-	ParentId    uint   `json:"parentId"`
-	Path        string `json:"path"`
-	Name        string `json:"name"`
-	Hidden      bool   `json:"hidden"`
-	Component   string `json:"component"`
-	Meta        `json:"meta"`
-	Children    []Menu `json:"children"`
-}
-
-type Meta struct {
-	Title string `json:"title"`
-	Icon  string `json:"icon"`
-}
-
-//获取动态路由树
-func (m *Menu) GetMenuTree(authorityId float64) (err error, menus []Menu) {
-	err = qmsql.DEFAULTDB.Where("authority_id = ? AND parent_id = ?", authorityId, 0).Find(&menus).Error
-	for i := 0; i < len(menus); i++ {
-		err = getChildrenList(&menus[i])
-	}
-	return err, menus
-}
-
-func getChildrenList(menu *Menu) (err error) {
-	err = qmsql.DEFAULTDB.Where("authority_id = ? AND parent_id = ?", menu.AuthorityId, menu.ID).Find(&menu.Children).Error
-	for i := 0; i < len(menu.Children); i++ {
-		err = getChildrenList(&menu.Children[i])
-	}
-	return err
-}

+ 75 - 0
QMPlusServer/model/dbModel/menu_authority.go

@@ -0,0 +1,75 @@
+package dbModel
+
+import (
+	"fmt"
+	"main/init/qmsql"
+)
+
+type Menu struct {
+	BaseMenu
+	MenuId      string `json:"menuId"`
+	AuthorityId string `json:"-"`
+	Children    []Menu `json:"children"`
+}
+
+type Meta struct {
+	Title string `json:"title"`
+	Icon  string `json:"icon"`
+}
+
+// 为角色增加menu树
+func (m *Menu) AddMenuAuthority(menus []BaseMenu, authorityId string) (err error) {
+	var menu Menu
+	qmsql.DEFAULTDB.Where("authority_id = ? ", authorityId).Unscoped().Delete(&Menu{})
+	for _, v := range menus {
+		menu.BaseMenu = v
+		menu.AuthorityId = authorityId
+		menu.MenuId = fmt.Sprintf("%v", v.ID)
+		menu.ID = 0
+		err = qmsql.DEFAULTDB.Create(&menu).Error
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// 查看当前角色树
+func (m *Menu) GetMenuAuthority(authorityId string) (err error, menus []Menu) {
+	err = qmsql.DEFAULTDB.Where("authority_id = ?", authorityId).Find(&menus).Error
+	return err, menus
+}
+
+//获取动态路由树
+func (m *Menu) GetMenuTree(authorityId float64) (err error, menus []Menu) {
+	err = qmsql.DEFAULTDB.Where("authority_id = ? AND parent_id = ?", authorityId, 0).Find(&menus).Error
+	for i := 0; i < len(menus); i++ {
+		err = getChildrenList(&menus[i])
+	}
+	return err, menus
+}
+
+func getChildrenList(menu *Menu) (err error) {
+	err = qmsql.DEFAULTDB.Where("authority_id = ? AND parent_id = ?", menu.AuthorityId, menu.MenuId).Find(&menu.Children).Error
+	for i := 0; i < len(menu.Children); i++ {
+		err = getChildrenList(&menu.Children[i])
+	}
+	return err
+}
+
+//获取基础路由树
+func (m *BaseMenu) GetBaseMenuTree() (err error, menus []BaseMenu) {
+	err = qmsql.DEFAULTDB.Where(" parent_id = ?", 0).Find(&menus).Error
+	for i := 0; i < len(menus); i++ {
+		err = getBaseChildrenList(&menus[i])
+	}
+	return err, menus
+}
+
+func getBaseChildrenList(menu *BaseMenu) (err error) {
+	err = qmsql.DEFAULTDB.Where("parent_id = ?", menu.ID).Find(&menu.Children).Error
+	for i := 0; i < len(menu.Children); i++ {
+		err = getBaseChildrenList(&menu.Children[i])
+	}
+	return err
+}

+ 5 - 0
QMPlusServer/router/menu.go

@@ -10,5 +10,10 @@ func InitMenuRouter(Router *gin.Engine) {
 	MenuRouter := Router.Group("menu").Use(middleware.JWTAuth())
 	{
 		MenuRouter.POST("getMenu", api.GetMenu)
+		MenuRouter.POST("getMenuList", api.GetMenuList)
+		MenuRouter.POST("addBaseMenu", api.AddBaseMenu)
+		MenuRouter.POST("getBaseMenuTree", api.GetBaseMenuTree)
+		MenuRouter.POST("addMenuAuthority", api.AddMenuAuthority)
+		MenuRouter.POST("getMenuAuthority", api.GetMenuAuthority)
 	}
 }

+ 63 - 0
QMPlusVuePage/src/api/menu.js

@@ -9,4 +9,67 @@ export const asyncMenu = () => {
         url: "/menu/getMenu",
         method: 'post',
     })
+}
+
+// @Summary 获取menu列表
+// @Produce  application/json
+// @Param {
+//  page     int
+//	pageSize int
+// }
+// @Router /menu/getMenuList [post]
+export const getMenuList = (data) => {
+    return service({
+        url: "/menu/getMenuList",
+        method: 'post',
+        data
+    })
+}
+
+
+// @Summary 获取menu列表
+// @Produce  application/json
+// @Param menu Object
+// @Router /menu/getMenuList [post]
+export const addBaseMenu = (data) => {
+    return service({
+        url: "/menu/addBaseMenu",
+        method: 'post',
+        data
+    })
+}
+
+// @Summary 获取基础路由列表
+// @Produce  application/json
+// @Param 可以什么都不填 调一下即可
+// @Router /menu/getBaseMenuTree [post]
+export const getBaseMenuTree = () => {
+    return service({
+        url: "/menu/getBaseMenuTree",
+        method: 'post',
+    })
+}
+
+// @Summary 添加用户menu关联关系
+// @Produce  application/json
+// @Param menus Object authorityId string
+// @Router /menu/getMenuList [post]
+export const addMenuAuthority = (data) => {
+    return service({
+        url: "/menu/addMenuAuthority",
+        method: 'post',
+        data
+    })
+}
+
+// @Summary 获取用户menu关联关系
+// @Produce  application/json
+// @Param authorityId string
+// @Router /menu/getMenuAuthority [post]
+export const getMenuAuthority = (data) => {
+    return service({
+        url: "/menu/getMenuAuthority",
+        method: 'post',
+        data
+    })
 }

+ 12 - 13
QMPlusVuePage/src/view/layout/index.vue

@@ -1,8 +1,6 @@
 <template>
   <el-container class="layout-cont">
-    <el-header class="header-cont">
-   
-    </el-header>
+    <el-header class="header-cont"></el-header>
     <el-container>
       <el-aside class="main-cont main-left">
         <Aside class="aside" />
@@ -12,7 +10,11 @@
         <el-main class="main-cont main-right">
           <!-- 当前面包屑用路由自动生成可根据需求修改 -->
           <el-breadcrumb class="breadcrumb" separator-class="el-icon-arrow-right">
-            <el-breadcrumb-item v-for="item in matched.slice(1,matched.length)" :key="item.path" :to="{ path: item.path }">{{item.meta.title}}</el-breadcrumb-item>
+            <el-breadcrumb-item
+              :key="item.path"
+              :to="{ path: item.path }"
+              v-for="item in matched.slice(1,matched.length)"
+            >{{item.meta.title}}</el-breadcrumb-item>
           </el-breadcrumb>
           <transition mode="out-in" name="el-fade-in-linear">
             <router-view></router-view>
@@ -38,16 +40,13 @@ export default {
       this.$bus.emit('totalCollapse')
     }
   },
-  computed:{
-    title(){
-      return this.$route.meta.title||'当前页面'
+  computed: {
+    title() {
+      return this.$route.meta.title || '当前页面'
     },
-    matched(){
+    matched() {
       return this.$route.matched
     }
-  },
-  created(){
-    console.log(this.$route.matched)
   }
 }
 </script>
@@ -68,13 +67,13 @@ $mainHight: calc(100vh - 52px);
     background: palevioletred;
   }
   .main-cont {
-    .breadcrumb{
+    .breadcrumb {
       line-height: 24px;
       padding: 6px;
       border-bottom: 1px solid #eee;
       margin-bottom: 6px;
     }
-    &.el-main{
+    &.el-main {
       padding: 0px 10px;
       margin: 0px 0px 0px 12px;
       background: #fff;

+ 184 - 4
QMPlusVuePage/src/view/superAdmin/menu/menu.vue

@@ -1,14 +1,194 @@
 <template>
-    <div>
-        新建菜单
+  <div>
+    <div class="button-box clearflex">
+      <el-button @click="addMenu('0')" type="primary">新增根菜单</el-button>
     </div>
+    <el-table :data="tableData" border stripe>
+      <el-table-column label="ID" min-width="80" prop="ID"></el-table-column>
+      <el-table-column label="路径" min-width="180" prop="path"></el-table-column>
+      <el-table-column label="名称" min-width="180" prop="name"></el-table-column>
+      <el-table-column label="是否隐藏" min-width="180" prop="hidden"></el-table-column>
+      <el-table-column label="父节点Id" min-width="180" prop="parentId"></el-table-column>
+      <el-table-column label="文件路径" min-width="180" prop="component"></el-table-column>
+      <el-table-column label="展示名称" min-width="180" prop="authorityName">
+        <template slot-scope="scope">
+          <span>{{scope.row.meta.title}}</span>
+        </template>
+      </el-table-column>
+       <el-table-column label="图标" min-width="180" prop="authorityName">
+        <template slot-scope="scope">
+          <span>{{scope.row.meta.icon}}</span>
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" width="100">
+        <template slot-scope="scope">
+          <el-button @click="addMenu(scope.row.ID)" size="small" type="text">添加子菜单</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      :current-page="page"
+      :page-size="pageSize"
+      :page-sizes="[10, 30, 50, 100]"
+      :style="{float:'right',padding:'20px'}"
+      :total="total"
+      @current-change="handleCurrentChange"
+      @size-change="handleSizeChange"
+      hide-on-single-page
+      layout="total, sizes, prev, pager, next, jumper"
+    ></el-pagination>
+
+    <el-dialog :visible.sync="dialogFormVisible" title="新增角色">
+      <el-form :inline="true" :model="form" label-width="80px">
+        <el-form-item label="路径">
+          <el-input autocomplete="off" v-model="form.path"></el-input>
+        </el-form-item>
+        <el-form-item label="名称">
+          <el-input autocomplete="off" v-model="form.name"></el-input>
+        </el-form-item>
+        <el-form-item label="是否隐藏">
+          <el-select placeholder="是否在列表隐藏" v-model="form.hidden">
+            <el-option :value="false" label="否"></el-option>
+            <el-option :value="true" label="是"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="父节点Id">
+          <el-input autocomplete="off" disabled v-model="form.parentId"></el-input>
+        </el-form-item>
+        <el-form-item label="文件路径">
+          <el-input autocomplete="off" v-model="form.component"></el-input>
+        </el-form-item>
+        <el-form-item label="展示名称">
+          <el-input autocomplete="off" v-model="form.meta.title"></el-input>
+        </el-form-item>
+        <el-form-item label="图标">
+          <el-input autocomplete="off" v-model="form.meta.icon"></el-input>
+        </el-form-item>
+      </el-form>
+      <div class="dialog-footer" slot="footer">
+        <el-button @click="closeDialog">取 消</el-button>
+        <el-button @click="enterDialog" type="primary">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
+import { getMenuList, addBaseMenu } from '@/api/menu'
 export default {
-    name:"Menus",
+  name: 'Menus',
+  data() {
+    return {
+      page: 1,
+      total: 10,
+      pageSize: 10,
+      tableData: [],
+      dialogFormVisible: false,
+      form: {
+        path: '',
+        name: '',
+        hidden: '',
+        parentId: '',
+        component: '',
+        meta: {
+          title: '',
+          icon: ''
+        }
+      }
+    }
+  },
+  methods: {
+    handleSizeChange(val) {
+      this.pageSize = val
+      this.getMenuList()
+    },
+    handleCurrentChange(val) {
+      this.page = val
+      this.getMenuList()
+    },
+    deleteAuth(row) {
+      this.$confirm('此操作将永久删除所有角色下该菜单, 是否继续?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(async () => {
+          try {
+            const res = await deleteAuthority({ authorityId: row.authorityId })
+            this.$message({
+              type: 'success',
+              message: '删除成功!'
+            })
+            this.getAuthList()
+          } catch (err) {
+            this.$message({
+              type: 'error',
+              message: '删除失败!' + err
+            })
+          }
+        })
+        .catch(() => {
+          this.$message({
+            type: 'info',
+            message: '已取消删除'
+          })
+        })
+    },
+    initForm() {
+      this.form = {
+        path: '',
+        name: '',
+        hidden: '',
+        parentId: '',
+        component: '',
+        meta: {
+          title: '',
+          icon: ''
+        }
+      }
+    },
+    closeDialog() {
+      this.initForm()
+      this.dialogFormVisible = false
+    },
+    async enterDialog() {
+      const res = await addBaseMenu(this.form)
+      if (res.success) {
+        this.$message({
+          type: 'success',
+          message: '添加成功!'
+        })
+        this.getAuthList()
+        this.closeDialog()
+      } else {
+        this.$message({
+          type: 'error',
+          message: '添加失败!'
+        })
+        this.closeDialog()
+      }
+      this.initForm()
+      this.dialogFormVisible = false
+    },
+    addMenu(id) {
+      this.form.parentId = String(id)
+      this.dialogFormVisible = true
+    },
+    async getMenuList(page = this.page, pageSize = this.pageSize) {
+        const table = await getMenuList({ page, pageSize })
+        this.tableData = table.data.menuList
+    }
+  },
+  created() {
+    this.getMenuList()
+  }
 }
 </script>
 <style lang="scss">
-    
+.button-box {
+  padding: 10px 20px;
+  .el-button {
+    float: right;
+  }
+}
 </style>