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(() => [