Browse Source

权限管理调整

huwei 1 month ago
parent
commit
cd3a9c3fdf

+ 4 - 4
server/.gitignore

@@ -6,12 +6,12 @@ logs
 logs.*
 *.exe
 main
-gadmin
-!gadmin/
+cadmin
+!cadmin/
 console
 !console/
 temp/
 resource/public/backup/
-resource/public/gadmin/
+resource/public/cadmin/
 resource/public/json/
-go.sum
+go.sum

BIN
server/cadmin


+ 7 - 8
server/config/menu.go

@@ -102,23 +102,22 @@ func GetMenuName(p string) string {
 	//return ""
 }
 
-func GetAllOptions() map[string]*model.AdminOperation {
-	menus := make(map[string]*model.AdminOperation)
+func GetAllOptions() []*model.AdminOperation {
 	q := AdminDB.Model(&model.AdminOperation{})
 	allOperation := make([]*model.AdminOperation, 0)
 	err := q.Find(&allOperation).Error
 	if err != nil {
 		logrus.Error("GetAllOptions", "err", err)
-		return menus
-	}
-	for _, item := range allOperation {
-		menus[item.API] = item
 	}
-	return menus
+	return allOperation
 }
 
 func HasMenu(p string) bool {
-	menus := GetAllOptions()
+	allOptions := GetAllOptions()
+	menus := make(map[string]*model.AdminOperation)
+	for _, item := range allOptions {
+		menus[item.API] = item
+	}
 	_, ok := menus[p]
 	return ok
 }

+ 2 - 2
server/internal/admin/middleware/token.go

@@ -89,9 +89,9 @@ func Token() gin.HandlerFunc {
 			return
 		}
 		config.TokenRedis.HSet(key, t, time.Now().Unix())
-		config.TokenRedis.Expire(key, config.TokenExpireTime)
+		config.TokenRedis.Expire(key, time.Hour*12)
 
-		config.TokenRedis.Expire(tokenKey, config.TokenExpireTime)
+		config.TokenRedis.Expire(tokenKey, time.Hour*12)
 
 		//if os.Getenv("GIN_MODE") == "release" && claims.UserName == "mojun" {
 		//	c.JSON(200, serializer.CheckLogin())

+ 6 - 6
server/internal/admin/server/router.go

@@ -51,7 +51,7 @@ func NewEngine() *gin.Engine {
 		group.GET("ping", api.Ping)                  // ping
 		group.GET("download/json", api.JsonResource) // 内部代理下载资源
 		//group.POST("user/register", api.UserRegister) // 用户注册
-		group.POST("user/login", api.UserLogin) // 用户登录
+		//group.POST("user/login", api.UserLogin) // 用户登录
 		//group.GET("service/list", api.ServiceList)      // 服务列表
 		//group.POST("service/select", api.ServiceSelect) // 选择系统
 		group.GET("deploy/notify", api.DeployNotify)
@@ -66,17 +66,17 @@ func NewEngine() *gin.Engine {
 		peripherals.POST("receiveCdk", api.PeripheralsReceiveCdk)
 		peripherals.GET("announcement/info", api.AnnouncementInfo) // 获取游戏更新公告
 
-		feishu := group.Group("feishu")
+		//feishu := group.Group("feishu")
 		//feishu.Use(middleware.ApiToken())
-		feishu.GET("feiShuUserLogin", api.FeiShuUserInfoLogin)
+		//feishu.GET("feiShuUserLogin", api.FeiShuUserInfoLogin)
 
 		// 只需要验证token的
 		checkToken := group.Group("")
 		checkToken.Use(middleware.Token())
 		{
-			checkToken.GET("service/list", api.ServiceList)                // 服务列表
-			checkToken.POST("service/select", api.ServiceSelect)           // 选择系统
-			checkToken.GET("user/checkRolePermission", api.RolePermission) // 管理员用户是否拥有权限管理
+			checkToken.GET("service/list", api.ServiceList)      // 服务列表
+			checkToken.POST("service/select", api.ServiceSelect) // 选择系统
+			//checkToken.GET("user/checkRolePermission", api.RolePermission) // 管理员用户是否拥有权限管理
 		}
 
 		// 需要登录保护的

+ 4 - 0
web/src/utils/http/axios/index.ts

@@ -19,6 +19,7 @@ import { CreateAxiosOptions, RequestOptions, Result } from './types';
 import { useUserStoreWidthOut } from '@/store/modules/user';
 import router from '@/router';
 import { storage } from '@/utils/Storage';
+import {getBaseLoginUrl} from "@/utils/env";
 
 const globSetting = useGlobSetting();
 const urlPrefix = globSetting.urlPrefix || '';
@@ -126,7 +127,10 @@ const transform: AxiosTransform = {
       case ResultEnum.TIMEOUT || ResultEnum.NO_RIGHT_ERR:
         const LoginName = PageEnum.BASE_LOGIN_NAME;
         // const LoginPath = PageEnum.BASE_LOGIN;
+        storage.clear();
         if (router.currentRoute.value?.name === LoginName) return;
+        window.open(getBaseLoginUrl(), '_self');
+        return;
         // 到登录页
         errorMsg = '登录超时,请重新登录!';
         $dialog.warning({

+ 2 - 2
web/src/views/announcement/columns.ts

@@ -3,12 +3,12 @@ import { h } from 'vue';
 
 export const columns = [
   {
-    title: '广播标题',
+    title: '公告标题',
     key: 'title',
     width: 200,
   },
   {
-    title: '广播内容',
+    title: '公告内容',
     key: 'content',
     width: 460,
     render(rows) {

+ 1 - 4
web/src/views/announcement/index.vue

@@ -203,11 +203,8 @@
 
   function handleEdit(record: Recordable) {
     title.value = '编辑公告';
-    formParams.value.date = [record.start_at * 1000, record.end_at * 1000];
+    formParams.value.title = record.title;
     formParams.value.content = record.content;
-    formParams.value.send_interval = record.send_interval;
-    formParams.value.notice_type = record.notice_type;
-    formParams.value.id = record.id;
     showModal.value = true;
 
     console.log('点击了编辑', record);

+ 97 - 7
web/src/views/permission/role/role.vue

@@ -72,7 +72,7 @@
         </n-form-item>
 
         <n-form-item label="系统分配" path="key">
-          <n-checkbox-group v-model:value="formParams.systems" @update:value="handleUpdateValue">
+          <n-checkbox-group v-model:value="formSystems" @update:value="handleUpdateValue">
             <n-space item-style="display: flex;">
               <n-checkbox
                 v-for="item in systems"
@@ -93,13 +93,44 @@
               :tab="item.name || item.id"
             >
               <n-form-item label="权限分配">
+                <div class="checkbox-group-wrapper">
+                  <n-space vertical>
+                    <n-checkbox
+                      :indeterminate="isIndeterminate(item.id)"
+                      :checked="isAllChecked(item.id)"
+                      @update:checked="(checked) => handleCheckAll(checked, item.id)"
+                    >
+                      全选
+                    </n-checkbox>
+                    <n-checkbox-group
+                      v-model:value="permissions[item.id]"
+                      @update:value="(newValue) => handlePermissionsUpdateValue(newValue, item.id)"
+                    >
+                      <n-space
+                        item-style="display: flex;"
+                        align="center"
+                        class="checkbox-container"
+                      >
+                        <n-checkbox
+                          v-for="option in optionsPermissions"
+                          :key="option.value"
+                          :value="option.value"
+                          :label="option.label"
+                        />
+                      </n-space>
+                    </n-checkbox-group>
+                  </n-space>
+                </div>
+              </n-form-item>
+
+              <!--              <n-form-item label="权限分配">
                 <n-select
                   multiple
                   v-model:value="formParams.permissions[item.id]"
                   :options="optionsPermissions"
                   @update:value="(newValue) => handlePermissionsUpdateValue(newValue, item.id)"
                 />
-              </n-form-item>
+              </n-form-item>-->
 
               <n-form-item label="页面分配">
                 <n-tree-select
@@ -158,18 +189,24 @@
 
   // 根据选中的checkbox生成active的tab panes
   const activeTabPanes = computed(() => {
-    if (!formParams.value.systems) {
-      formParams.value.systems = [];
+    if (!formSystems.value) {
+      formSystems.value = [];
     }
-    return systems.value.filter((tab) => formParams.value.systems.includes(tab.id));
+    return systems.value.filter((tab) => formSystems.value.includes(tab.id));
   });
 
+  const selectSystem = ref<any>([]);
+
   function handleUpdateValue(values) {
     // 找出新增的选项
-    const added = values.filter((item) => !formParams.value.systems.includes(item));
+    const added = values.filter((item) => !selectSystem.value.includes(item));
     // 如果有新增的tab,默认激活第一个新增的tab
     if (added.length > 0) {
       activeTab.value = added[0];
+      added.forEach((item) => {
+        pages.value[item] = formParams.value.pages[item] || [];
+        permissions.value[item] = formParams.value.permissions[item] || [];
+      });
     }
     // 如果当前激活的tab被移除了,则激活第一个可用的tab
     else if (!values.includes(activeTab.value)) {
@@ -185,10 +222,33 @@
         delete permissions.value[valueKey];
       }
     }
+    selectSystem.value = values;
   }
 
   const pages = ref<object>({});
   const permissions = ref<object>({});
+  const formSystems = ref<any>([]);
+
+  // 检查是否全部选中
+  const isAllChecked = (id) => {
+    return permissions.value[id]?.length === optionsPermissions.value.length;
+  };
+
+  // 检查是否是部分选中(不确定状态)
+  const isIndeterminate = (id) => {
+    const selectedCount = permissions.value[id]?.length || 0;
+    return selectedCount > 0 && selectedCount < optionsPermissions.value.length;
+  };
+
+  // 处理全选/全不选
+  const handleCheckAll = (checked, sysId) => {
+    if (checked) {
+      permissions.value[sysId] = optionsPermissions.value.map((opt) => opt.value);
+      // formParams.value.permissions[sysId] = optionsPermissions.value.map((opt) => opt.value);
+    } else {
+      permissions.value[sysId] = [];
+    }
+  };
 
   function handlePermissionsUpdateValue(val: any, sysId: number) {
     permissions.value[sysId] = val;
@@ -252,6 +312,7 @@
   }
 
   function confirmForm(e: any) {
+    formParams.value.systems = formSystems.value;
     formParams.value.permissions = permissions.value;
     formParams.value.pages = pages.value;
     e.preventDefault();
@@ -281,6 +342,8 @@
     formParams.value = cloneDeep(record);
     pages.value = record.pages;
     permissions.value = record.permissions;
+    formSystems.value = record.systems;
+    selectSystem.value = record.systems;
     activeTab.value = record.systems[0];
   }
 
@@ -296,4 +359,31 @@
   });
 </script>
 
-<style lang="less" scoped></style>
+<style lang="less" scoped>
+  .checkbox-group-wrapper {
+    border: 1px solid #eee;
+    padding: 12px;
+    border-radius: 3px;
+  }
+
+  .checkbox-container {
+    max-height: 300px; /* 设置最大高度 */
+    overflow-y: auto; /* 超出时显示垂直滚动条 */
+    padding-right: 8px; /* 为滚动条留出空间 */
+    display: flex;
+    flex-direction: column;
+    gap: 8px; /* 设置选项之间的间距 */
+  }
+
+  /* 滚动条样式 */
+  .checkbox-container::-webkit-scrollbar {
+    width: 6px;
+  }
+  .checkbox-container::-webkit-scrollbar-thumb {
+    background-color: #d9d9d9;
+    border-radius: 3px;
+  }
+  .checkbox-container::-webkit-scrollbar-thumb:hover {
+    background-color: #c1c1c1;
+  }
+</style>