Prechádzať zdrojové kódy

Merge branch 'dev' of http://121.40.98.15:3001/kym/charge-java into dev

skyline 2 rokov pred
rodič
commit
a388006006
21 zmenil súbory, kde vykonal 717 pridanie a 321 odobranie
  1. 1 1
      admin-web/src/utils/request.ts
  2. 7 7
      admin-web/src/views/admin/role/dialog.vue
  3. 278 170
      admin-web/src/views/admin/role/index.vue
  4. 131 79
      admin-web/src/views/admin/user/dialog.vue
  5. 6 2
      admin-web/src/views/admin/user/index.vue
  6. 39 4
      admin/src/main/java/com/kym/admin/controller/AdminUserController.java
  7. 36 0
      admin/src/main/java/com/kym/admin/controller/PermissionController.java
  8. 73 0
      admin/src/main/java/com/kym/admin/controller/RoleController.java
  9. 11 15
      entity/src/main/java/com/kym/entity/admin/Permission.java
  10. 3 7
      entity/src/main/java/com/kym/entity/admin/Role.java
  11. 12 0
      entity/src/main/java/com/kym/entity/admin/vo/AdminUserRoleVo.java
  12. 2 2
      mapper/src/main/java/com/kym/mapper/admin/PermissionMapper.java
  13. 1 1
      mapper/src/main/java/com/kym/mapper/admin/RoleMapper.java
  14. 5 8
      mapper/src/main/resources/mappers/admin/PermissionMapper.xml
  15. 1 4
      mapper/src/main/resources/mappers/admin/RoleMapper.xml
  16. 6 0
      service/src/main/java/com/kym/service/admin/AdminUserService.java
  17. 2 2
      service/src/main/java/com/kym/service/admin/PermissionService.java
  18. 15 4
      service/src/main/java/com/kym/service/admin/RoleService.java
  19. 40 0
      service/src/main/java/com/kym/service/admin/impl/AdminUserServiceImpl.java
  20. 3 5
      service/src/main/java/com/kym/service/admin/impl/PermissionServiceImpl.java
  21. 45 10
      service/src/main/java/com/kym/service/admin/impl/RoleServiceImpl.java

+ 1 - 1
admin-web/src/utils/request.ts

@@ -43,7 +43,7 @@ service.interceptors.response.use(
     (response) => {
         // 对响应数据做点什么
         const res = response.data;
-        console.log(res)
+        // console.log(res)
         if (res.code && res.code !== 0) {
             // `token` 过期或者账号已在别处登录
             if (res.code === 401) {

+ 7 - 7
admin-web/src/views/admin/role/dialog.vue

@@ -10,29 +10,29 @@
                   <span>角色名称</span>
                 </el-tooltip>
               </template>
-              <el-input v-model="state.ruleForm.roleAlias" placeholder="请输入角色标识" clearable></el-input>
+              <el-input v-model="state.ruleForm.roleName" placeholder="请输入角色标识" clearable></el-input>
             </el-form-item>
           </el-col>
 
           <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
             <el-form-item label="角色别名" prop="roleAlias">
-              <el-input v-model="state.ruleForm.name" placeholder="请输入角色别名" clearable></el-input>
+              <el-input v-model="state.ruleForm.roleDesc" placeholder="请输入角色别名" clearable></el-input>
             </el-form-item>
           </el-col>
-
+<!--
           <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
             <el-form-item label="排序">
               <el-input-number v-model="state.ruleForm.weight" :min="0" :max="999" controls-position="right" placeholder="请输入排序" class="w100"/>
             </el-form-item>
-          </el-col>
+          </el-col>-->
           <!--          <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" class="mb20">
                       <el-form-item label="角色状态">
                         <el-switch v-model="state.ruleForm.status" inline-prompt active-text="启" inactive-text="禁"></el-switch>
                       </el-form-item>
                     </el-col>-->
           <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
-            <el-form-item label="角色描述">
-              <el-input v-model="state.ruleForm.remark" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
+            <el-form-item label="权限组">
+              <el-input readonly  v-model="state.ruleForm.permissions" type="textarea" placeholder="请输入角色描述" ></el-input>
             </el-form-item>
           </el-col>
           <!--          <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
@@ -42,7 +42,7 @@
                     </el-col>-->
           <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
             <span style="margin-left: 5px">
-              <el-button :disabled="state.ruleForm.immutable" type="danger" @click="handleDelete" size="default">删除角色</el-button>
+              <el-button  type="danger" @click="handleDelete" size="default">删除角色</el-button>
             </span>
           </el-col>
 

+ 278 - 170
admin-web/src/views/admin/role/index.vue

@@ -1,220 +1,328 @@
-<style scoped lang="scss">
-.system-container {
-
-  :deep(.el-card__body) {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    flex: 1;
-    overflow: auto;
-
-    .el-table {
-      flex: 1;
-    }
-
-  }
-}
-
-.page-content {
-  margin-bottom: 20px;
-}
-
-.page-pager {
-  background-color: #fff;
-  height: 24px;
-}
-</style>
 <template>
-  <div class="system-container layout-padding">
-    <el-card shadow="hover" class="layout-padding-auto">
-
-
-      <el-form
-          :model="state.formQuery"
-          ref="queryRef"
-          size="default" label-width="0px" class="mt5 mb5">
-        <el-input
-            v-model="state.formQuery.roleName"
-            placeholder="角色名"
-            clearable
-            @blur="loadData(true)"
-            class="wd150 mr10">
-        </el-input>
-
-
-        <el-button class="ml10"  plain size="default" type="success" @click="loadData(true)">
-          <SvgIcon name="ele-Search"/>
-          查询
+  <div class="system-role-container layout-padding">
+    <div class="system-role-padding layout-padding-auto layout-padding-view">
+      <div class="system-user-search mb15">
+        <el-input v-model="state.formQuery.roleName"  clearable size="default"
+                  placeholder="请输入角色名称" style="max-width: 180px"></el-input>
+
+        <ext-button icon="ele-Search" type="primary" plain class="ml10" @click="loadData"  name="查询"/>
+        <!--        <el-button size="default" type="primary" class="ml10">-->
+        <!--          <el-icon>-->
+        <!--            <ele-Search/>-->
+        <!--          </el-icon>-->
+        <!--          查询-->
+        <!--        </el-button>-->
+        <el-button size="default" type="success" class="ml10" @click="handleOpenDialog(0,false)">
+          <el-icon>
+            <ele-FolderAdd/>
+          </el-icon>
+          新增角色
         </el-button>
-      </el-form>
-
+        <el-button v-if="state.changed" size="default" type="success" class="ml10" @click="handleSaveRolePermission">
+          <SvgIcon name="ele-Printer"/>
+          保存设置
+        </el-button>
+      </div>
       <el-table
-          :header-cell-style="{background:'#eef1f6',color:'#606266'}"
-          border
-          stripe="stripe"
-          :height="state.tableData.height"
-          highlight-current-row
-          current-row-key="id"
-          row-key="id"
+          ref="tableRef"
           :data="state.tableData.data"
           v-loading="state.tableData.loading"
-          @selection-change="handleTableSelectionChange"
-          @sort-change="handleTableSortChange">
+          border
+          row-key="id"
+          :tree-props="{children:'children'}"
+          @cell-click="handleToggleRoleCheck"
+          style="width: 100%">
         <template #empty>
           <el-empty></el-empty>
         </template>
         <el-table-column
-            v-for="field in state.tableData.columns"
-            :key="field.prop"
-            :label="field.label"
-            :column-key="field.prop"
-            :width="field.width"
-            :min-width="field.minWidth"
-            :fixed="field.fixed"
-            :sortable="field.sortable"
-            :show-overflow-tooltip="!field.fixed&&field.width>150"
-        >
-          <template #default="{row}">
-            <template v-if="field.prop==='expand'">
-              <p style="padding-left: 2em;" v-html="row[field.prop]"></p>
+            v-for="(col,idx) in state.columns"
+            :key="col.prop"
+            :label="col.label"
+            :width="col.width"
+            :min-width="col.minWidth"
+            show-overflow-tooltip
+            :fixed="col.fixed"
+            :align="col.prop==='permName'?'left':'center'">
+          <template #header>
+            <template v-if="idx>0">
+              <div class="role-header-item">{{ col.label }}
+                <SvgIcon v-if="!state.immutableRoleList.includes(col.prop)" name="ele-Setting"
+                         @click="handleOpenDialog(col.prop.split('_')[1],false)"/>
+              </div>
             </template>
-            <template v-else>
-              <div>{{row[field.prop]}}</div>
+            <template v-if="idx===0">
+              权限
+              <span style="cursor: pointer;font-size: 12px;margin-left: 8px;color:#ccc" @click="handleExpandSwitch">{{state.expandAll?'收起':'展开'}} </span>
             </template>
-
+          </template>
+          <template #default="scope">
+            <template v-if="scope.column.label!=='权限'">
+              <el-icon color="#5FB878" v-if="scope.row[col.prop]">
+                <CircleCheckFilled/>
+              </el-icon>
+              <span v-else>
+                  <SvgIcon name="ele-CircleCheck"></SvgIcon>
+                </span>
+            </template>
+            <template v-else ><span :title="scope.row.perm">{{ scope.row[col.prop] }}</span></template>
           </template>
         </el-table-column>
       </el-table>
+    </div>
+
 
-      <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
-    </el-card>
+    <RoleDialog ref="roleDialogRef" @refresh="loadData()"/>
   </div>
-<!--  <RoleDialog ref="roleDialogRef" @refresh="loadData(true)"/>-->
 </template>
 
-<script setup lang="ts" name="RoleList">
-import {defineAsyncComponent, reactive, onMounted, onBeforeMount, ref, getCurrentInstance, nextTick, onBeforeUnmount} from 'vue';
-import {$body,$get} from "/@/utils/request";
+<script setup lang="ts" name="systemRole">
+import {defineAsyncComponent, reactive, onMounted, ref,nextTick} from 'vue';
+import {$body, $get} from "/@/utils/request";
+import u from "/@/utils/u";
 import {Msg} from "/@/utils/message";
+import {CircleCheckFilled} from '@element-plus/icons-vue'
+import ExtButton from "/@/components/form/ExtButton.vue";
 
+// 引入组件
+const RoleDialog = defineAsyncComponent(() => import('/@/views/admin/role/dialog.vue'));
 
-import ExtPage from '/@/components/form/ExtPage.vue'
-
-import mittBus from '/@/utils/mitt';
-
-// const RoleDialog = defineAsyncComponent(() => import("/@/views/page/RoleDialog.vue"));
-
-//定义引用
-const queryRef = ref();
+const tableRef = ref();
+// 定义变量内容
 const roleDialogRef = ref();
-
-//定义变量
 const state = reactive({
-  formQuery: {},
-  pageQuery: {
-    pageNum: 1,
-    pageSize: 10,
-    total: 0
-  },
   tableData: {
-    height: 500,
-    data: [] as Array < any >,
+    data: [] as Array<any>,
     loading: false,
-    columns: [
-      {label: '角色名', prop: 'roleName', resizable: true},
-      {label: '角色描述', prop: 'roleDesc', resizable: true},
-      {label: '角色列表', prop: 'permissions', resizable: true},
-      {label: '创建时间', prop: 'createTime', sortable: 'custom', resizable: true},
-      {label: '更新时间', prop: 'updateTime', sortable: 'custom', resizable: true},
-      {
-        label: '操作', prop: 'action', width: 180, align: 'center', fixed: 'right',
-      }
-    ],
   },
-})
-
-
-// 监听双向绑定 modelValue 的变化
-// watch(
-//         () => state.pageIndex,
-//         () => {
-//
-//         }
-// );
-
-//生命周期钩子
-onBeforeMount(() => {
-})
-
-onMounted(() => {
-  loadData();
+  pageQuery: {
+    pageIndex: 1,
+    pageSize: 20,
+  },
+  formQuery: {
+    roleName: null,
+  },
+  columns: [{label: '权限', prop: 'permName', width: 200, fixed: 'left'}] as Array<IBaseField>,
+  expandAll: false,
+  immutableRoleList: [] as Array<string>,
+  changed : false
+});
 
-  nextTick(() => {
-    let bodyHeight = document.body.clientHeight;
-    let queryHeight = queryRef.value.$el.clientHeight;
-    state.tableData.height = bodyHeight - queryHeight - 320
+const handleExpandSwitch = ()=>{
+  state.expandAll = !state.expandAll;
+  nextTick(()=>{
+    state.tableData.data.forEach(row=>{
+      tableRef.value.toggleRowExpansion(row,state.expandAll);
+    })
   })
+}
 
-  mittBus.on("role.refresh", () => {
-    loadData();
-  })
-});
+const loadPermissionList = (roleList: Array<any>) => {
+  $get(`/permission/listPermission`, {pageSize: -1}).then((res: any) => {
+    //构造权限数组
+    let data = [] as Array<any>;
+    var permMap = u.groupByKey(res, "pid");
+    console.log(permMap)
+    let roleMap = new Map();
+    state.immutableRoleList = [] as Array<string>;
+    roleList.forEach(role => {
+      state.columns.push({
+        label: role.roleName,
+        prop: 'role_' + role.id,
+        width: (role.roleName).length * 24 + 45,
+      });
+      roleMap.set(role.id, role)
+    });
+    console.log(state.columns)
+    let topPermissionList = permMap['0']
+    if (u.isEmptyOrNull(topPermissionList)) {
+      Msg.message("没有权限数据", 'error')
+      state.tableData.loading = false;
+      return;
+    }
 
-onBeforeUnmount(() => {
-  mittBus.off("role.refresh")
-})
+    topPermissionList.forEach((top: any) => {
+      let {id, name, value} = top;
+      let childrenPermissionList = permMap[id.toString()];
+      let record = {
+        children: [] as Array<any>,
+        permName: name,
+        id: id,
+        perm: value,
+        // hasChildren: !u.isEmptyOrNull(childrenPermissionList)
+      } as any;
+      roleList.forEach(role => {
+        record['role_' + role.id] = !!(role.permissions && role.permissions.includes(value));
+      })
+
+      let children = [] as Array<any>;
+      if (!u.isEmptyOrNull(childrenPermissionList)) {
+        childrenPermissionList.forEach((child: any) => {
+          let childRecord = {
+            permName: child.name,
+            id: child.id,
+            perm: child.value,
+          } as any;
+          roleList.forEach(role => {
+            childRecord['role_' + role.id] = !!(role.permissions && role.permissions.includes(child.value));
+          })
+          children.push(childRecord);
+        });
+        //
+        record.children = children;
+      }
+      data.push(record);
+    })
 
 
-//region 方法区
+    state.tableData.data = data;
+    console.log(state.tableData.data)
+    state.tableData.loading = false;
+  }).catch(e => {
+    //console.log(e)
+    state.tableData.loading = false;
+  })
+}
 // 初始化表格数据
-const loadData = (refresh: boolean = false) => {
-  if (refresh) {
-    state.pageQuery.pageNum = 1;
-  }
+const loadData = () => {
+  state.columns = [{label: '权限', prop: 'permName', width: 120, fixed: 'left'}];
+  state.tableData.data = [];
   state.tableData.loading = true;
-  $get(`/admin-user/listRole`, {...state.formQuery, ...state.pageQuery}).then((res: any) => {
-    let {list, total} = res;
-    state.tableData.data = list;
-    state.pageQuery.total = total;
-    state.tableData.loading = false;
+  $get(`/role/list`, {...state.formQuery}).then((res: any) => {
+    //构造权限数组
+    loadPermissionList(res);
   }).catch(e => {
     console.error(e)
     state.tableData.loading = false;
   })
 };
-
-// 打开修改用户弹窗
-const onRowClick = (type: string, row: any) => {
-  roleDialogRef.value.open(type, row);
+// 打开新增角色弹窗
+const handleOpenDialog = (id: number, readonly: boolean) => {
+  roleDialogRef.value.openDialog(id, readonly);
 };
 
-// 删除用户
-const onRowDel = (row: any) => {
-  Msg.confirm(`此操作将永久删除:『${row.name}』,是否继续?`).then(() => {
-    $get(`/role/delete/${row.id}`).then(() => {
-      Msg.message("删除成功", 'success')
-    }).catch(() => {
-      Msg.message("删除失败", 'error')
+const handleToggleRoleCheck = (row, column, cell, event) => {
+  state.changed = true;
+  console.log(row, column, cell)
+  if(column.rawColumnKey==='permName'){
+    // tableRef.value
+    return;
+  }
+
+  let index = state.tableData.data.findIndex(k => k.id === row.id);
+  if (index >= 0) {
+    let record = state.tableData.data[index];
+    //console.log(record)
+    let bol = !record[column.rawColumnKey];
+    state.tableData.data[index][column.rawColumnKey] = bol;
+    if (!u.isEmptyOrNull(record.children)) {
+      record.children.forEach((r:any)=>{
+        r[column.rawColumnKey]= bol;
+      })
+    }
+  } else {
+    state.tableData.data.forEach(record => {
+      if (!u.isEmptyOrNull(record.children)) {
+        let r = record.children.find((k: any) => k.id === row.id);
+        if (r) {
+          r[column.rawColumnKey] = !r[column.rawColumnKey]
+          return;
+        }
+      }
     })
-  });
-};
+  }
+}
+
 
-const handleTableSelectionChange = (selection: any) => {
-  console.log("handleTableSelectionChange>>", selection)
-  // emit("on-check-change", selection)
+const handleSaveRolePermission = () => {
+  let updateRoles = [] as Array<any>;
+  let map = new Map();
+
+  let keys = Object.keys(state.tableData.data[0])
+  console.log(state.tableData.data)
+  state.tableData.data.forEach(record => {
+    keys.forEach((k: string) => {
+      if (k.startsWith("role_")) {
+        if (record[k]) {
+          let roleId = k.split("_")[1];
+          let newVar = map.get(roleId);
+          if (!newVar) {
+            map.set(roleId, [record.perm])
+          } else {
+            newVar.push(record.perm);
+            map.set(roleId, newVar);
+          }
+        }
+      }
+      if (!u.isEmptyOrNull(record.children)) {
+        record.children.forEach((child: any) => {
+          if (k.startsWith("role_")) {
+            if (child[k]) {
+              let roleId = k.split("_")[1];
+              let newVar = map.get(roleId);
+              if (!newVar) {
+                map.set(roleId, [child.perm])
+              } else {
+                newVar.push(child.perm);
+                map.set(roleId, newVar);
+              }
+            }
+
+          }
+        })
+      }
+    })
+  })
+
+  //console.log(map)
+  map.forEach((value: Array<string>, key: any) => {
+    updateRoles.push({
+      id: Number(key),
+      permissions: value.join("|")
+    });
+  })
+
+  $body(`/role/saveList`,updateRoles).then(()=>{
+    Msg.message("更新成功","success");
+    state.changed = false;
+    nextTick(()=>{
+      loadData();
+    })
+  })
 }
 
-const handleTableSortChange = (column, prop, order) => {
-  console.log("handleTableSortChange>>", column, prop, order)
-  // emit("on-sort-change", column)
+// 页面加载时
+onMounted(() => {
+  loadData();
+});
+</script>
+
+<style scoped lang="scss">
+.role-header-item {
+  display: inline-flex;
+  justify-content: space-around;
+  align-items: center;
+
+  i {
+    margin-left: 3px;
+    cursor: pointer;
+  }
 }
 
+.permission-box {
+}
 
-//endregion
+.system-role-container {
+  .system-role-padding {
+    padding: 15px;
 
+    .el-table {
+      flex: 1;
+    }
+  }
+}
 
-// 暴露变量
-// defineExpose({
-//     loadData,
-// });
-</script>
+:deep(.el-table thead th.el-table__cell ) {
+  background: var(--el-fill-color-light);
+}
+</style>

+ 131 - 79
admin-web/src/views/admin/user/dialog.vue

@@ -3,39 +3,100 @@
 </style>
 <template>
   <div class="system-dialog-container">
-
-    <el-dialog
+    <el-drawer
         :title="state.dialog.title"
         v-model="state.dialog.isShowDialog"
-        width="820px"
-        draggable
+        size="620px"
+        append-to-body
         destroy-on-close
         :close-on-click-modal="false"
-        align-center>
-      <el-skeleton :rows="5" animated v-if="state.loading"/>
-      <ext-detail-form v-else
-                       ref="formRef"
-                       v-model="state.ruleForm"
-                       :columns="state.columns"
-                       :rules="state.rules"
-                       @on-change="handleFormChange"
-      ></ext-detail-form>
+    >
+      <el-form
+          :model="state.ruleForm"
+          :rules="state.rules"
+          label-position="top"
+          ref="formRef"
+          size="default"
+          label-width="100px"
+          class="mt5 pd10">
+        <el-form-item label="用户名">
+          <el-input
+              v-model="state.ruleForm.username"
+              placeholder="用户名"
+              clearable
+              class="w100">
+          </el-input>
+        </el-form-item>
+        <el-form-item label="昵称">
+          <el-input
+              v-model="state.ruleForm.nickname"
+              placeholder="昵称"
+              clearable
+              class="w100">
+          </el-input>
+        </el-form-item>
+        <el-form-item label="手机号">
+          <el-input
+              v-model="state.ruleForm.mobilePhone"
+              placeholder="手机号"
+              clearable
+              class="w100">
+          </el-input>
+        </el-form-item>
+        <el-form-item label="头像">
+          <el-input
+              v-model="state.ruleForm.avatar"
+              placeholder="头像"
+              clearable
+              class="w100">
+          </el-input>
+        </el-form-item>
+        <el-form-item label="状态">
+          <ext-d-select
+              type="AdminUser.status"
+              v-model="state.ruleForm.status"
+              placeholder="状态"
+              clearable
+              class="w100">
+          </ext-d-select>
+        </el-form-item>
+        <el-form-item label="最后登录时间" v-if="state.ruleForm.id>0">
+          <el-input
+              v-model="state.ruleForm.lastLoginTime"
+              placeholder="最后登录时间"
+              clearable
+              readonly
+              class="w100">
+          </el-input>
+        </el-form-item>
+
+        <el-card header="角色">
+          <el-checkbox-group
+              v-model="state.checkRoleIdList"
+              @change="handleCheckedRoleChange"
+          >
+            <el-checkbox v-for="role in state.roleList" :key="role.id" :label="role.id">{{role.roleName}}</el-checkbox>
+          </el-checkbox-group>
+        </el-card>
+      </el-form>
 
       <template #footer>
-				<span class="dialog-footer">
-					<el-button @click="onCancel" size="default">取 消</el-button>
-					<el-button :loading="state.btnLoading" type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
-				</span>
+        <div class="dialog-footer">
+          <el-button @click="onCancel" size="default">取 消</el-button>
+          <el-button :loading="state.btnLoading" type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
+        </div>
       </template>
-    </el-dialog>
+    </el-drawer>
   </div>
 </template>
 
-<script setup lang="ts" name="UserDialog">
+<script setup lang="ts" name="AdminUserDialog">
 import {defineAsyncComponent, reactive, onMounted, ref} from 'vue';
 import {Msg} from "/@/utils/message";
 import {$body, $get} from "/@/utils/request";
 import u from '/@/utils/u'
+import type {FormInstance, FormRules} from 'element-plus';
+import ExtDSelect from "/@/components/form/ExtDSelect.vue";
 
 // 引入组件
 const ExtDetailForm = defineAsyncComponent(() => import('/@/components/form/ExtDetailForm.vue'));
@@ -48,7 +109,6 @@ const initState = () => ({
   ruleForm: {
     id: 0
   },
-  loading: true,
   btnLoading: false,
   dialog: {
     isShowDialog: false,
@@ -56,46 +116,9 @@ const initState = () => ({
     title: '',
     submitTxt: '',
   },
-  columns: [
-    {label: '基本信息', prop: 'un', type: 'divider', align: 'left'},
-    {label: '头像', prop: 'avatar', type: 'avatar',},
-    {label: '用户名', prop: 'userName', type: "text",tips:'用来登录的名称',rules:[u.validator.required]},
-    {label: '名称', prop: 'name', type: 'text',tips:'用来展示的名称',rules:[u.validator.required]},
-    {label: '手机号', prop: 'mobile', type: 'text',},
-    {
-      label: '用户状态',
-      prop: 'status',
-      sortable: 'custom',
-      align: 'center',
-      type: 'dict',
-      conf: {dict: 'User.status'}
-    },
-    {label: '职业信息', prop: 'un', type: 'divider', align: 'left'},
-    {label: '工号', prop: 'code', type: 'text',},
-    {label: '邮箱', prop: 'email', type: 'text',},
-    {label: '所属部门', prop: 'deptIdList', type: 'dept',conf:{multiple:true}},
-    {label: '分配角色', prop: 'roleIdList', type: 'select',conf:{multiple:true,url: 'entity/list', query: {entity: 'role'}}},
-    {label: '岗位职责', prop: 'postIdList', type: 'search',conf:{multiple:true,url: 'entity/list', query: {entity: 'post'}}},
-    {label: 'boss权限', prop: 'boss', type: 'dict',conf:{dict:'User.boss'}},
-    {label: '职业', prop: 'job', type: 'text',},
-    {label: '上级领导', prop: 'leaderId', type: 'user',},
-
-
-    {label: '其他信息', prop: 'un', type: 'divider', align: 'left'},
-    {label: '本次登录地址', prop: 'ip', type: 'text',},
-    {label: '上次登录地址', prop: 'lastIp', type: 'text',},
-    {
-      label: '上次登录时间', prop: 'lastLoginAt', type: 'datetime',
-    },
-    {
-      label: '创建时间', prop: 'createAt', type: 'datetime',
-    },
-    {label: '备注', prop: 'remark', type: 'textarea',conf:{max:500,rowspan:3}},
-    {
-      label: '更新时间', prop: 'updateAt', type: 'datetime',
-    },
-  ],
   rules: {},
+  roleList:[],
+  checkRoleIdList:[]
 })
 
 // 定义变量内容
@@ -104,15 +127,19 @@ const state = reactive(initState());
 
 // 打开弹窗
 const open = (action: string = 'add', row: any) => {
-  state.dialog.title = u.dialog.actions[action].title + "『用户信息』"
-  state.dialog.submitTxt = u.dialog.actions[action].btn + "『用户信息』"
+  loadRole();
+  state.dialog.title = u.dialog.actions[action].title + "『运营用户』"
+  state.dialog.submitTxt = u.dialog.actions[action].btn + "『运营用户』"
   state.dialog.isShowDialog = true;
   if (action !== 'add') {
     loadData(row.id);
-  } else {
-    state.loading = false;
   }
+
 };
+
+const handleCheckedRoleChange = ()=>{
+  }
+
 // 关闭弹窗
 const onClose = () => {
   state.dialog.isShowDialog = false;
@@ -124,33 +151,58 @@ const onCancel = () => {
 };
 // 提交
 const onSubmit = () => {
-  formRef.value.checkForm().then(() => {
-    state.btnLoading = true;
-    const url = state.ruleForm.id > 0 ? "user/modify" : "user/add"
-    $body(url, state.ruleForm).then(() => {
+  formRef.value.validate((valid, fields) => {
+    // console.log('basic checkForm!', valid,fields)
+    if (valid) {
+      state.btnLoading = true;
+      const url = state.ruleForm.id > 0 ? "admin-user/modify" : "admin-user/add"
+      $body(url, state.ruleForm).then(() => {
+        state.btnLoading = false;
+        Msg.message('操作成功');
+        console.log('submit!')
+        if(state.ruleForm.id>0){
+          $body(`admin-user/updateRole`,{userId:state.ruleForm.id,roleIdList:state.checkRoleIdList}).then(()=>{
+            onClose();
+            emit('refresh');
+          })
+        }else{
+          onClose();
+          emit('refresh');
+        }
+      })
+    } else {
       state.btnLoading = false;
-      Msg.message();
-      console.log('submit!')
-      onClose();
-      emit('refresh');
-    })
-  }).catch(() => {
-    state.btnLoading = false;
-    Msg.message('请完整填写表单', 'error');
+      Msg.message('表单校验失败', 'error');
+    }
   })
+
+  // formRef.value.checkForm().then(() => {
+  //
+  // }).catch(() => {
+  //     state.btnLoading = false;
+  //     Msg.message('表单校验失败', 'error');
+  // })
 };
 
 const handleFormChange = (formData: any) => {
   console.log(formData)
 }
 
+const loadRole = ()=>{
+  $get(`role/list`).then((res: any) => {
+    state.roleList = res;
+  })
+}
+
 // 初始化表格数据
 const loadData = (id: number) => {
-  $get(`user/detail/${id}`).then((res: any) => {
-    // let {user} = res;
-    state.ruleForm = res;
-    setTimeout(()=>state.loading = false,200)
+  $get(`admin-user/detail/${id}`).then((res: any) => {
+    let {adminUser, roles} = res;
+    state.ruleForm = adminUser;
+    state.checkRoleIdList = roles.map(k=>k.roleId)
   })
+
+
 }
 
 // 暴露变量

+ 6 - 2
admin-web/src/views/admin/user/index.vue

@@ -110,6 +110,9 @@
             <template v-else-if="'status'===field.prop">
               <ext-d-label type="AdminUser.status" v-model="row[field.prop]"/>
             </template>
+            <template v-else-if="'action'===field.prop">
+             <el-button  size="small" plain  type="warning" @click="onRowClick('edit',row)">编辑</el-button>
+            </template>
             <template v-else>
               <div>{{row[field.prop]}}</div>
             </template>
@@ -121,7 +124,7 @@
       <ext-page class="page-pager" v-model:value="state.pageQuery" @change="loadData(false)"/>
     </el-card>
   </div>
-<!--  <AdminUserDialog ref="adminUserDialogRef" @refresh="loadData(true)"/>-->
+  <AdminUserDialog ref="adminUserDialogRef" @refresh="loadData(true)"/>
 </template>
 
 <script setup lang="ts" name="AdminUserList">
@@ -136,7 +139,7 @@ import mittBus from '/@/utils/mitt';
 import ExtDSelect from "/@/components/form/ExtDSelect.vue";
 import ExtDLabel from "/@/components/form/ExtDLabel.vue";
 
-// const AdminUserDialog = defineAsyncComponent(() => import("/@/views/page/AdminUserDialog.vue"));
+const AdminUserDialog = defineAsyncComponent(() => import("/@/views/admin/user/dialog.vue"));
 
 //定义引用
 const queryRef = ref();
@@ -201,6 +204,7 @@ onBeforeUnmount(() => {
 
 
 //region 方法区
+
 // 初始化表格数据
 const loadData = (refresh: boolean = false) => {
   if (refresh) {

+ 39 - 4
admin/src/main/java/com/kym/admin/controller/AdminUserController.java

@@ -6,10 +6,18 @@ import com.kym.common.R;
 import com.kym.common.annotation.SysLog;
 import com.kym.common.controller.IController;
 import com.kym.entity.admin.queryParams.CommonQueryParam;
+import com.kym.entity.admin.vo.AdminUserRoleVo;
 import com.kym.entity.admin.vo.AdminUserVo;
 import com.kym.service.admin.AdminUserService;
 import com.kym.service.admin.RoleService;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
 
 /**
  * <p>
@@ -68,20 +76,47 @@ public class AdminUserController extends IController {
      * @param adminUserVo
      * @return
      */
-    @PostMapping
+    @PostMapping("add")
     R<?> createAdminUser(@RequestBody AdminUserVo adminUserVo) {
         adminUserService.createAdminUser(adminUserVo);
         return R.success();
     }
 
 
+    /**
+     * 新增操作员
+     *
+     * @param adminUserVo
+     * @return
+     */
+    @PostMapping("modify")
+    R<?> updateAdminUser(@RequestBody AdminUserVo adminUserVo) {
+        adminUserService.updateAdminUser(adminUserVo);
+        return R.success();
+    }
+
+
     /**
      * 角色列表
      *
      * @return
      */
     @GetMapping("listRole")
-    R<?> listRole(@ModelAttribute CommonQueryParam params) {
-        return R.success(roleService.listRole(params));
+    R<?> listRole() {
+        return R.success(roleService.listRole(null));
     }
+
+    @GetMapping("detail/{id}")
+    public R<?> detail(@PathVariable(name = "id") int id) {
+        return resp(() -> adminUserService.detail(id));
+    }
+
+    //    @SaCheckPermission("")
+    @PostMapping("updateRole")
+    R<?> updateRole(@RequestBody AdminUserRoleVo vo) {
+        adminUserService.updateRole(vo.getUserId(), vo.getRoleIdList());
+        return R.success();
+    }
+
+
 }

+ 36 - 0
admin/src/main/java/com/kym/admin/controller/PermissionController.java

@@ -0,0 +1,36 @@
+package com.kym.admin.controller;
+
+import com.kym.common.R;
+import com.kym.service.admin.PermissionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * 权限 前端控制器
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-09-23
+ */
+@RestController
+@RequestMapping("/permission")
+public class PermissionController {
+
+    private PermissionService permissionService;
+
+    @Autowired
+    public void setPermissionService(PermissionService permissionService) {
+        this.permissionService = permissionService;
+    }
+
+    @GetMapping("listPermission")
+    R listPermission() {
+        var res = permissionService.lambdaQuery().list();
+        return R.success(res);
+    }
+
+}

+ 73 - 0
admin/src/main/java/com/kym/admin/controller/RoleController.java

@@ -0,0 +1,73 @@
+package com.kym.admin.controller;
+
+import com.kym.common.R;
+import com.kym.common.controller.IController;
+import com.kym.entity.admin.Role;
+import com.kym.service.admin.RoleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+
+/**
+ * <p>
+ * 角色表 前端控制器
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-09-23
+ */
+@RestController
+@RequestMapping("/role")
+public class RoleController extends IController {
+
+    private RoleService roleService;
+
+    @Autowired
+    public void setRoleService(RoleService roleService) {
+        this.roleService = roleService;
+    }
+
+
+    @GetMapping("list")
+    public R<?>  listRole(String roleName) {
+        return resp(()->roleService.listRole(roleName));
+    }
+
+
+    @PostMapping("add")
+    public R<?>  add(@RequestBody Role role) {
+        return resp(() -> roleService.add(role));
+    }
+
+    @PostMapping("modify")
+    public R<?> modify(@RequestBody Role role) {
+        return resp((t) -> roleService.modify(role));
+    }
+
+
+    @PostMapping("delete/{id}")
+    public R<?>  delete(@PathVariable (name = "id") int id) {
+        return resp((t) -> roleService.remove(id));
+    }
+
+
+    @GetMapping("detail/{id}")
+    public R<?>  detail(@PathVariable (name = "id") int id) {
+        return resp(() -> roleService.detail(id));
+    }
+
+
+
+    @PostMapping("saveList")
+    public R<?>  saveList(@RequestBody List<Role> roleList) {
+        return resp((t) -> roleService.saveList(roleList));
+    }
+
+}

+ 11 - 15
entity/src/main/java/com/kym/entity/admin/Permission.java

@@ -5,42 +5,38 @@ import com.kym.entity.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
 /**
  * <p>
- * 权限
+ * 权限
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 @Getter
 @Setter
 @TableName("t_permission")
-public class Permission extends BaseEntity implements Serializable {
+public class Permission extends BaseEntity {
 
     private static final long serialVersionUID = 1L;
 
     /**
-     * 公司id
+     * 权限名称
      */
-    private Long companyId;
+    private String name;
 
     /**
-     * 父权限id
+     * 权限码值
      */
-    private Long parentId;
+    private String value;
 
     /**
-     * 权限
+     * 父级权限
      */
-    private String permissionName;
+    private int pid;
 
     /**
-     * 权限描述
+     * 排序权重
      */
-    private String permissionDesc;
-
+    private Integer weight;
 }

+ 3 - 7
entity/src/main/java/com/kym/entity/admin/Role.java

@@ -5,21 +5,18 @@ import com.kym.entity.BaseEntity;
 import lombok.Getter;
 import lombok.Setter;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
 /**
  * <p>
  * 角色表
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 @Getter
 @Setter
 @TableName("t_role")
-public class Role extends BaseEntity implements Serializable {
+public class Role extends BaseEntity {
 
     private static final long serialVersionUID = 1L;
 
@@ -44,8 +41,7 @@ public class Role extends BaseEntity implements Serializable {
     private String roleDesc;
 
     /**
-     * 权限
+     * 角色列表
      */
     private String permissions;
-
 }

+ 12 - 0
entity/src/main/java/com/kym/entity/admin/vo/AdminUserRoleVo.java

@@ -0,0 +1,12 @@
+package com.kym.entity.admin.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+
+@Data
+public class AdminUserRoleVo {
+    private long userId;
+    private List<Long> roleIdList;
+}

+ 2 - 2
mapper/src/main/java/com/kym/mapper/admin/PermissionMapper.java

@@ -5,11 +5,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
  * <p>
- * 权限 Mapper 接口
+ * 权限 Mapper 接口
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 public interface PermissionMapper extends BaseMapper<Permission> {
 

+ 1 - 1
mapper/src/main/java/com/kym/mapper/admin/RoleMapper.java

@@ -9,7 +9,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 public interface RoleMapper extends BaseMapper<Role> {
 

+ 5 - 8
mapper/src/main/resources/mappers/admin/PermissionMapper.xml

@@ -4,18 +4,15 @@
 
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="com.kym.entity.admin.Permission">
-        <id column="id" property="id" />
-        <result column="company_id" property="companyId" />
-        <result column="parent_id" property="parentId" />
-        <result column="permission_name" property="permissionName" />
-        <result column="permission_desc" property="permissionDesc" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
+        <result column="name" property="name" />
+        <result column="value" property="value" />
+        <result column="pid" property="pid" />
+        <result column="weight" property="weight" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, parent_id, permission_name, permission_desc, create_time, update_time
+        `name`, `value`, `pid`, weight
     </sql>
 
 </mapper>

+ 1 - 4
mapper/src/main/resources/mappers/admin/RoleMapper.xml

@@ -4,19 +4,16 @@
 
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="com.kym.entity.admin.Role">
-        <id column="id" property="id" />
         <result column="company_id" property="companyId" />
         <result column="parent_id" property="parentId" />
         <result column="role_name" property="roleName" />
         <result column="role_desc" property="roleDesc" />
         <result column="permissions" property="permissions" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, parent_id, role_name, role_desc, permissions,create_time, update_time
+        company_id, parent_id, role_name, role_desc, permissions
     </sql>
 
 </mapper>

+ 6 - 0
service/src/main/java/com/kym/service/admin/AdminUserService.java

@@ -31,4 +31,10 @@ public interface AdminUserService extends IService<AdminUser> {
     PageBean<AdminUserVo> listAdminUser(CommonQueryParam params);
 
     void createAdminUser(AdminUserVo adminUserVo);
+
+    Object detail(int id);
+
+    void updateRole(long userId, List<Long> roleIdList);
+
+    void updateAdminUser(AdminUserVo adminUserVo);
 }

+ 2 - 2
service/src/main/java/com/kym/service/admin/PermissionService.java

@@ -5,11 +5,11 @@ import com.baomidou.mybatisplus.extension.service.IService;
 
 /**
  * <p>
- * 权限 服务类
+ * 权限 服务类
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 public interface PermissionService extends IService<Permission> {
 

+ 15 - 4
service/src/main/java/com/kym/service/admin/RoleService.java

@@ -2,8 +2,9 @@ package com.kym.service.admin;
 
 import com.kym.entity.admin.Role;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.kym.entity.admin.queryParams.CommonQueryParam;
-import com.kym.entity.common.PageBean;
+
+import java.util.List;
+
 
 /**
  * <p>
@@ -11,9 +12,19 @@ import com.kym.entity.common.PageBean;
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 public interface RoleService extends IService<Role> {
 
-    PageBean<Role> listRole(CommonQueryParam params);
+    Object listRole(String roleName);
+
+    Object add(Role role);
+
+    void modify(Role role);
+
+    void remove(int id);
+
+    void saveList(List<Role> roleList);
+
+    Role detail(int id);
 }

+ 40 - 0
service/src/main/java/com/kym/service/admin/impl/AdminUserServiceImpl.java

@@ -1,15 +1,18 @@
 package com.kym.service.admin.impl;
 
 import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.crypto.asymmetric.KeyType;
 import cn.hutool.crypto.asymmetric.RSA;
 import cn.hutool.crypto.digest.DigestAlgorithm;
 import cn.hutool.crypto.digest.Digester;
 import com.baomidou.dynamic.datasource.annotation.DS;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.pagehelper.PageHelper;
 import com.kym.common.R;
 import com.kym.common.constant.ResponseEnum;
+import com.kym.common.utils.CommUtil;
 import com.kym.common.utils.IDGenerator;
 import com.kym.entity.admin.AdminUser;
 import com.kym.entity.admin.AdminUserRole;
@@ -25,6 +28,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
@@ -121,4 +125,40 @@ public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser
                 .setRoleId(adminUserVo.getRoleId());
         adminUserRoleService.save(adminUserRole);
     }
+
+    @Override
+    public Object detail(int id) {
+        AdminUser adminUser = baseMapper.selectById(id);
+        adminUser.setPassword(null);
+        List<AdminUserRole> userRoleList = adminUserRoleService.lambdaQuery().eq(AdminUserRole::getAdminUserId, id).list();
+        return Map.of("adminUser",adminUser,"roles",userRoleList);
+    }
+
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void updateRole(long userId, List<Long> roleIdList) {
+        QueryWrapper wrapper = new QueryWrapper();
+        wrapper.eq("admin_user_id",userId);
+        adminUserRoleService.remove(wrapper);
+        if(CommUtil.isEmptyOrNull(roleIdList)){
+            return;
+        }
+        roleIdList.forEach(roleId->{
+            AdminUserRole roleEntity = new AdminUserRole();
+            roleEntity.setAdminUserId(userId);
+            roleEntity.setRoleId(roleId);
+            roleEntity.setCreateTime(LocalDateTime.now());
+            roleEntity.setUpdateTime(LocalDateTime.now());
+            adminUserRoleService.save(roleEntity);
+        });
+
+    }
+
+    @Override
+    public void updateAdminUser(AdminUserVo adminUserVo) {
+        AdminUser entity = new AdminUser();
+        BeanUtil.copyProperties(adminUserVo,entity);
+        baseMapper.updateById(entity);
+    }
 }

+ 3 - 5
service/src/main/java/com/kym/service/admin/impl/PermissionServiceImpl.java

@@ -1,22 +1,20 @@
 package com.kym.service.admin.impl;
 
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kym.entity.admin.Permission;
 import com.kym.mapper.admin.PermissionMapper;
 import com.kym.service.admin.PermissionService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
 /**
  * <p>
- * 权限 服务实现类
+ * 权限 服务实现类
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 @Service
-@DS("db-admin")
 public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
 
 }

+ 45 - 10
service/src/main/java/com/kym/service/admin/impl/RoleServiceImpl.java

@@ -1,14 +1,16 @@
 package com.kym.service.admin.impl;
 
-import com.baomidou.dynamic.datasource.annotation.DS;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.github.pagehelper.PageHelper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.kym.common.utils.CommUtil;
 import com.kym.entity.admin.Role;
-import com.kym.entity.admin.queryParams.CommonQueryParam;
-import com.kym.entity.common.PageBean;
 import com.kym.mapper.admin.RoleMapper;
 import com.kym.service.admin.RoleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
 
 /**
  * <p>
@@ -16,15 +18,48 @@ import org.springframework.stereotype.Service;
  * </p>
  *
  * @author skyline
- * @since 2023-07-12
+ * @since 2023-09-23
  */
 @Service
-@DS("db-admin")
 public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
 
     @Override
-    public PageBean<Role> listRole(CommonQueryParam params) {
-        PageHelper.startPage(params.getPageNum(), params.getPageSize());
-        return new PageBean<>(list());
+    public Object listRole(String roleName) {
+        return lambdaQuery().eq(!CommUtil.isEmptyOrNull(roleName),Role::getRoleName,roleName).list();
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Object add(Role role) {
+        return save(role);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void modify(Role role) {
+        updateById(role);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void remove(int id) {
+        removeById(id);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void saveList(List<Role> roleList) {
+
+      roleList.forEach(role->{
+          UpdateWrapper update  = new UpdateWrapper();
+            update.eq("id",role.getId());
+            update.set("permissions",role.getPermissions());
+            baseMapper.update(role,update);
+      });
+    }
+
+    @Override
+    public Role detail(int id) {
+        return baseMapper.selectById(id);
     }
 }