diff --git a/.workbuddy/memory/2026-04-28.md b/.workbuddy/memory/2026-04-28.md index 349c0aa..bf93ab6 100644 --- a/.workbuddy/memory/2026-04-28.md +++ b/.workbuddy/memory/2026-04-28.md @@ -49,3 +49,12 @@ 2. 查询该组所有成员的 `TabUserGroupBinds` 记录 3. 提取所有 `UserID` 更新到 `sysAdmins` 缓存切片 4. 组不存在或查询失败时清空缓存 + +## Web 前端系统管理员入口 + +- 后端 `getinfo` 接口返回 `isSysAdmin` 布尔值(不再暴露完整管理员列表) +- 后端新增 `POST /users/sysadmins` 接口,仅系统管理员可访问,返回完整 `sysAdmins` 数组 +- 前端 `userStore`:`isSysAdmin` 改为 ref,直接从后端获取 +- `AppHeader.vue` 用户菜单:当 `isSysAdmin` 为 true 时显示「系统管理」入口(琥珀色盾牌图标) +- 新建 `SysAdminView.vue`:4 个标签页占位符(用户管理、用户组、登录日志、系统配置),页面内调用 `authApi.sysAdmins()` 获取管理员列表 +- 路由 `/sysadmin`:添加 `requireSysAdmin` 元信息,路由守卫拦截非管理员访问 diff --git a/backend/my_work/routers/apiUsers.go b/backend/my_work/routers/apiUsers.go index 0317331..e1a706f 100644 --- a/backend/my_work/routers/apiUsers.go +++ b/backend/my_work/routers/apiUsers.go @@ -575,8 +575,6 @@ func ApiUser(r *gin.RouterGroup) { isAuth, user, _ := AuthenticationAuthority(ctx) if isAuth { //载入用户info - - //fmt.Println(userInfo) var redata map[string]interface{} = make(map[string]interface{}) info := GetUserInfoFromUserID(user.ID) @@ -586,10 +584,47 @@ func ApiUser(r *gin.RouterGroup) { user.Salt = "" redata["user"] = user + // 只返回当前用户是否为系统管理员,不暴露完整列表 + isSysAdmin := false + for _, adminID := range sysAdmins { + if adminID == user.ID { + isSysAdmin = true + break + } + } + redata["isSysAdmin"] = isSysAdmin + ReturnJson(ctx, "apiOK", redata) } }) + + // 获取系统管理员列表(仅系统管理员可访问) + r.POST("/sysadmins", func(ctx *gin.Context) { + isAuth, user, _ := AuthenticationAuthority(ctx) + if !isAuth { + ReturnJson(ctx, "userNoLogin", nil) + return + } + + // 检查是否为系统管理员 + isSysAdmin := false + for _, adminID := range sysAdmins { + if adminID == user.ID { + isSysAdmin = true + break + } + } + if !isSysAdmin { + ReturnJson(ctx, "permission_denied", nil) + return + } + + var redata map[string]interface{} = make(map[string]interface{}) + redata["sysAdmins"] = sysAdmins + ReturnJson(ctx, "apiOK", redata) + }) + //用户登陆 r.POST("/login", func(ctx *gin.Context) { var loginuser From_user_login diff --git a/frontend/ops_vue_js/src/api/auth.js b/frontend/ops_vue_js/src/api/auth.js index 489ab6b..0e23db7 100644 --- a/frontend/ops_vue_js/src/api/auth.js +++ b/frontend/ops_vue_js/src/api/auth.js @@ -16,6 +16,11 @@ export const authApi = { return api.post('/users/getinfo', {}) }, + /** 获取系统管理员列表(仅管理员可访问) */ + sysAdmins() { + return api.post('/users/sysadmins', {}) + }, + /** 修改密码 */ changePassword(oldPass, newPass) { return api.post('/users/changePassword', { oldpass: oldPass, newpass: newPass }) diff --git a/frontend/ops_vue_js/src/components/AppHeader.vue b/frontend/ops_vue_js/src/components/AppHeader.vue index b35ce43..6e4dd73 100644 --- a/frontend/ops_vue_js/src/components/AppHeader.vue +++ b/frontend/ops_vue_js/src/components/AppHeader.vue @@ -11,6 +11,7 @@ import { IconSettings, IconMenu2, IconX, + IconShield, } from "@tabler/icons-vue"; const { t, locale } = useI18n(); @@ -149,6 +150,15 @@ const navItems = computed(() => [ {{ t("message.user_settings") }} + + + 系统管理 +