diff --git a/.workbuddy/memory/2026-04-28.md b/.workbuddy/memory/2026-04-28.md index bf93ab6..980f88a 100644 --- a/.workbuddy/memory/2026-04-28.md +++ b/.workbuddy/memory/2026-04-28.md @@ -53,8 +53,9 @@ ## Web 前端系统管理员入口 - 后端 `getinfo` 接口返回 `isSysAdmin` 布尔值(不再暴露完整管理员列表) -- 后端新增 `POST /users/sysadmins` 接口,仅系统管理员可访问,返回完整 `sysAdmins` 数组 +- 新建 `apiSysAdmin.go` 文件,专门处理系统管理员接口 +- 后端新增 `POST /admin/sysadmins` 接口(位于 apiSysAdmin.go),仅系统管理员可访问,返回完整 `sysAdmins` 数组 - 前端 `userStore`:`isSysAdmin` 改为 ref,直接从后端获取 - `AppHeader.vue` 用户菜单:当 `isSysAdmin` 为 true 时显示「系统管理」入口(琥珀色盾牌图标) - 新建 `SysAdminView.vue`:4 个标签页占位符(用户管理、用户组、登录日志、系统配置),页面内调用 `authApi.sysAdmins()` 获取管理员列表 -- 路由 `/sysadmin`:添加 `requireSysAdmin` 元信息,路由守卫拦截非管理员访问 +- 路由 `/admin`:添加 `requireSysAdmin` 元信息,路由守卫拦截非管理员访问 diff --git a/backend/my_work/routers/api.go b/backend/my_work/routers/api.go index aed2877..4e4b3fc 100644 --- a/backend/my_work/routers/api.go +++ b/backend/my_work/routers/api.go @@ -43,6 +43,7 @@ func ApiRoot(r *gin.RouterGroup) { ApiSchedule(r.Group("/schedule")) ApiWorkOrder(r.Group("/work_order")) ApiWarehouse(r.Group("/warehouse")) + ApiSysAdmin(r.Group("/admin")) r.GET("/", func(ctx *gin.Context) { ReturnJson(ctx, "apiOK", gin.H{ "isOpsApiRoot": true, diff --git a/backend/my_work/routers/apiSysAdmin.go b/backend/my_work/routers/apiSysAdmin.go new file mode 100644 index 0000000..9c3676f --- /dev/null +++ b/backend/my_work/routers/apiSysAdmin.go @@ -0,0 +1,45 @@ +package routers + +import ( + "github.com/gin-gonic/gin" +) + +// InitSysAdminRouter 初始化系统管理员路由 +func ApiSysAdmin(r *gin.RouterGroup) { + // 获取系统管理员列表(仅系统管理员可访问) + r.POST("/sysadmins", func(ctx *gin.Context) { + isAuth, user, _ := AuthenticationAuthority(ctx) + if !isAuth { + ReturnJson(ctx, "userNoLogin", nil) + return + } + + // 检查是否为系统管理员 + if !SysAdminCheck(user.ID) { + ReturnJson(ctx, "permission_denied", nil) + return + } + + var redata map[string]interface{} = make(map[string]interface{}) + redata["sysAdmins"] = sysAdmins + ReturnJson(ctx, "apiOK", redata) + }) + + // TODO: 其他系统管理员接口可在此添加 + // 例如:用户管理、用户组管理、登录日志查询等 +} + +// SysAdminCheck 检查当前用户是否为系统管理员 +func SysAdminCheck(userID uint) bool { + for _, adminID := range sysAdmins { + if adminID == userID { + return true + } + } + return false +} + +// RefreshSysAdmins 刷新系统管理员缓存(可从数据库重新加载) +func RefreshSysAdmins() { + updateSysAdminsCash() +} diff --git a/backend/my_work/routers/apiUsers.go b/backend/my_work/routers/apiUsers.go index e1a706f..6e4bf9b 100644 --- a/backend/my_work/routers/apiUsers.go +++ b/backend/my_work/routers/apiUsers.go @@ -599,32 +599,6 @@ func ApiUser(r *gin.RouterGroup) { } }) - // 获取系统管理员列表(仅系统管理员可访问) - 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 0e23db7..131d6d9 100644 --- a/frontend/ops_vue_js/src/api/auth.js +++ b/frontend/ops_vue_js/src/api/auth.js @@ -18,7 +18,7 @@ export const authApi = { /** 获取系统管理员列表(仅管理员可访问) */ sysAdmins() { - return api.post('/users/sysadmins', {}) + return api.post('/admin/sysadmins', {}) }, /** 修改密码 */ diff --git a/frontend/ops_vue_js/src/api/index.js b/frontend/ops_vue_js/src/api/index.js index ad088fb..cf02bd1 100644 --- a/frontend/ops_vue_js/src/api/index.js +++ b/frontend/ops_vue_js/src/api/index.js @@ -95,6 +95,14 @@ export const api = { return unwrapResponse(res) }, + /** + * POST JSON (原始格式,不包装 data 层) + */ + async postRaw(path, payload = {}) { + const res = await http.post(path, payload) + return unwrapResponse(res) + }, + /** * POST FormData(文件上传) */ diff --git a/frontend/ops_vue_js/src/components/AppHeader.vue b/frontend/ops_vue_js/src/components/AppHeader.vue index 6e4dd73..6fb7f73 100644 --- a/frontend/ops_vue_js/src/components/AppHeader.vue +++ b/frontend/ops_vue_js/src/components/AppHeader.vue @@ -19,6 +19,7 @@ const router = useRouter(); const route = useRoute(); const userStore = useUserStore(); + const isDark = ref(document.documentElement.classList.contains("dark")); const mobileMenuOpen = ref(false); const userDropdownOpen = ref(false); @@ -152,7 +153,7 @@ const navItems = computed(() => [ @@ -225,6 +226,15 @@ const navItems = computed(() => [ {{ t("message.user_settings") }} + + + 系统管理 +