up
This commit is contained in:
@@ -53,8 +53,9 @@
|
|||||||
## Web 前端系统管理员入口
|
## Web 前端系统管理员入口
|
||||||
|
|
||||||
- 后端 `getinfo` 接口返回 `isSysAdmin` 布尔值(不再暴露完整管理员列表)
|
- 后端 `getinfo` 接口返回 `isSysAdmin` 布尔值(不再暴露完整管理员列表)
|
||||||
- 后端新增 `POST /users/sysadmins` 接口,仅系统管理员可访问,返回完整 `sysAdmins` 数组
|
- 新建 `apiSysAdmin.go` 文件,专门处理系统管理员接口
|
||||||
|
- 后端新增 `POST /admin/sysadmins` 接口(位于 apiSysAdmin.go),仅系统管理员可访问,返回完整 `sysAdmins` 数组
|
||||||
- 前端 `userStore`:`isSysAdmin` 改为 ref,直接从后端获取
|
- 前端 `userStore`:`isSysAdmin` 改为 ref,直接从后端获取
|
||||||
- `AppHeader.vue` 用户菜单:当 `isSysAdmin` 为 true 时显示「系统管理」入口(琥珀色盾牌图标)
|
- `AppHeader.vue` 用户菜单:当 `isSysAdmin` 为 true 时显示「系统管理」入口(琥珀色盾牌图标)
|
||||||
- 新建 `SysAdminView.vue`:4 个标签页占位符(用户管理、用户组、登录日志、系统配置),页面内调用 `authApi.sysAdmins()` 获取管理员列表
|
- 新建 `SysAdminView.vue`:4 个标签页占位符(用户管理、用户组、登录日志、系统配置),页面内调用 `authApi.sysAdmins()` 获取管理员列表
|
||||||
- 路由 `/sysadmin`:添加 `requireSysAdmin` 元信息,路由守卫拦截非管理员访问
|
- 路由 `/admin`:添加 `requireSysAdmin` 元信息,路由守卫拦截非管理员访问
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ func ApiRoot(r *gin.RouterGroup) {
|
|||||||
ApiSchedule(r.Group("/schedule"))
|
ApiSchedule(r.Group("/schedule"))
|
||||||
ApiWorkOrder(r.Group("/work_order"))
|
ApiWorkOrder(r.Group("/work_order"))
|
||||||
ApiWarehouse(r.Group("/warehouse"))
|
ApiWarehouse(r.Group("/warehouse"))
|
||||||
|
ApiSysAdmin(r.Group("/admin"))
|
||||||
r.GET("/", func(ctx *gin.Context) {
|
r.GET("/", func(ctx *gin.Context) {
|
||||||
ReturnJson(ctx, "apiOK", gin.H{
|
ReturnJson(ctx, "apiOK", gin.H{
|
||||||
"isOpsApiRoot": true,
|
"isOpsApiRoot": true,
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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) {
|
r.POST("/login", func(ctx *gin.Context) {
|
||||||
var loginuser From_user_login
|
var loginuser From_user_login
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export const authApi = {
|
|||||||
|
|
||||||
/** 获取系统管理员列表(仅管理员可访问) */
|
/** 获取系统管理员列表(仅管理员可访问) */
|
||||||
sysAdmins() {
|
sysAdmins() {
|
||||||
return api.post('/users/sysadmins', {})
|
return api.post('/admin/sysadmins', {})
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 修改密码 */
|
/** 修改密码 */
|
||||||
|
|||||||
@@ -95,6 +95,14 @@ export const api = {
|
|||||||
return unwrapResponse(res)
|
return unwrapResponse(res)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST JSON (原始格式,不包装 data 层)
|
||||||
|
*/
|
||||||
|
async postRaw(path, payload = {}) {
|
||||||
|
const res = await http.post(path, payload)
|
||||||
|
return unwrapResponse(res)
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST FormData(文件上传)
|
* POST FormData(文件上传)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ const router = useRouter();
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
|
||||||
const isDark = ref(document.documentElement.classList.contains("dark"));
|
const isDark = ref(document.documentElement.classList.contains("dark"));
|
||||||
const mobileMenuOpen = ref(false);
|
const mobileMenuOpen = ref(false);
|
||||||
const userDropdownOpen = ref(false);
|
const userDropdownOpen = ref(false);
|
||||||
@@ -152,7 +153,7 @@ const navItems = computed(() => [
|
|||||||
</RouterLink>
|
</RouterLink>
|
||||||
<RouterLink
|
<RouterLink
|
||||||
v-if="userStore.isSysAdmin"
|
v-if="userStore.isSysAdmin"
|
||||||
to="/sysadmin"
|
to="/admin"
|
||||||
class="flex items-center gap-2 px-4 py-2 text-sm text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-900/20"
|
class="flex items-center gap-2 px-4 py-2 text-sm text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-900/20"
|
||||||
@click="userDropdownOpen = false"
|
@click="userDropdownOpen = false"
|
||||||
>
|
>
|
||||||
@@ -225,6 +226,15 @@ const navItems = computed(() => [
|
|||||||
<IconSettings :size="16" />
|
<IconSettings :size="16" />
|
||||||
{{ t("message.user_settings") }}
|
{{ t("message.user_settings") }}
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
|
<RouterLink
|
||||||
|
v-if="userStore.isSysAdmin"
|
||||||
|
to="/admin"
|
||||||
|
class="flex items-center gap-2 px-4 py-2 text-sm text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-900/20"
|
||||||
|
@click="userDropdownOpen = false"
|
||||||
|
>
|
||||||
|
<IconShield :size="16" />
|
||||||
|
系统管理
|
||||||
|
</RouterLink>
|
||||||
<hr class="my-1 border-gray-200 dark:border-dk-muted" />
|
<hr class="my-1 border-gray-200 dark:border-dk-muted" />
|
||||||
<button
|
<button
|
||||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
|
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const router = createRouter({
|
|||||||
component: () => import('@/views/AdminView.vue'),
|
component: () => import('@/views/AdminView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'sysadmin',
|
path: 'admin',
|
||||||
name: 'sysadmin',
|
name: 'sysadmin',
|
||||||
component: () => import('@/views/SysAdminView.vue'),
|
component: () => import('@/views/SysAdminView.vue'),
|
||||||
meta: { requireSysAdmin: true },
|
meta: { requireSysAdmin: true },
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const userInfo = ref(null) // TabUserInfo_ 详情
|
const userInfo = ref(null) // TabUserInfo_ 详情
|
||||||
const userCookie = ref(null) // Cookie session
|
const userCookie = ref(null) // Cookie session
|
||||||
const isLoggedIn = ref(false)
|
const isLoggedIn = ref(false)
|
||||||
const sysAdmins = ref([]) // 系统管理员 ID 列表
|
|
||||||
|
|
||||||
// ── Getters ──
|
// ── Getters ──
|
||||||
const cookieValue = computed(() => userCookie.value?.Value ?? '')
|
const cookieValue = computed(() => userCookie.value?.Value ?? '')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user