统一角色体系为admin/agent/user,修复代理查询角色错误,添加语言切换和明暗切换
This commit is contained in:
@@ -308,7 +308,7 @@ func initData() {
|
||||
Username: "dev",
|
||||
Email: &devEmail,
|
||||
Password: string(hashedPassword),
|
||||
Role: "developer",
|
||||
Role: "admin",
|
||||
Status: "active",
|
||||
}
|
||||
DB.Create(&devUser)
|
||||
@@ -324,7 +324,7 @@ func initData() {
|
||||
Username: "agent",
|
||||
Email: &agentEmail,
|
||||
Password: string(hashedPassword),
|
||||
Role: "developer",
|
||||
Role: "agent",
|
||||
Status: "active",
|
||||
}
|
||||
DB.Create(&agentUser)
|
||||
@@ -678,7 +678,7 @@ func initTicketData() {
|
||||
Username: "dev",
|
||||
Email: &devEmail,
|
||||
Password: string(hashedPassword),
|
||||
Role: "developer",
|
||||
Role: "admin",
|
||||
Status: "active",
|
||||
}
|
||||
DB.Create(&devUser)
|
||||
|
||||
@@ -114,7 +114,7 @@ func AdminAuth() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// DeveloperAuth 开发者权限中间件
|
||||
// DeveloperAuth 开发者权限中间件(管理员即开发者)
|
||||
func DeveloperAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
role, exists := c.Get("role")
|
||||
@@ -124,8 +124,8 @@ func DeveloperAuth() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
if role != "developer" && role != "admin" {
|
||||
response.Error(c, http.StatusForbidden, "Developer access required")
|
||||
if role != "admin" {
|
||||
response.Error(c, http.StatusForbidden, "Admin access required")
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// User 平台用户模型(开发者、管理员)
|
||||
// User 平台用户模型(管理员、代理商)
|
||||
type User struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Username string `gorm:"uniqueIndex;size:50" json:"username"`
|
||||
|
||||
@@ -362,8 +362,8 @@ func handleInviteAgent(c *gin.Context) {
|
||||
response.Error(c, 404, "开发者不存在")
|
||||
return
|
||||
}
|
||||
if agent.Role != "developer" {
|
||||
response.Error(c, 400, "该用户不是开发者")
|
||||
if agent.Role != "agent" {
|
||||
response.Error(c, 400, "该用户不是代理商")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -421,8 +421,8 @@ func handleRequestAuthorization(c *gin.Context) {
|
||||
response.Error(c, 404, "开发者不存在")
|
||||
return
|
||||
}
|
||||
if developer.Role != "developer" {
|
||||
response.Error(c, 400, "该用户不是开发者")
|
||||
if developer.Role != "admin" {
|
||||
response.Error(c, 400, "该用户不是管理员")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ type AgentTreeNode struct {
|
||||
|
||||
func handleGetAgents(c *gin.Context) {
|
||||
var users []model.User
|
||||
if err := database.DB.Where("role = ?", "admin").
|
||||
if err := database.DB.Where("role = ?", "agent").
|
||||
Preload("ParentAgent").
|
||||
Order("created_at DESC").
|
||||
Find(&users).Error; err != nil {
|
||||
@@ -123,7 +123,7 @@ func handleGetAgents(c *gin.Context) {
|
||||
|
||||
func handleGetAgentsTree(c *gin.Context) {
|
||||
var users []model.User
|
||||
if err := database.DB.Where("role = ?", "admin").
|
||||
if err := database.DB.Where("role = ?", "agent").
|
||||
Preload("ParentAgent").
|
||||
Order("created_at DESC").
|
||||
Find(&users).Error; err != nil {
|
||||
@@ -239,7 +239,7 @@ func handleCreateAgent(c *gin.Context) {
|
||||
|
||||
if req.ParentAgentID != nil {
|
||||
var parentAgent model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", *req.ParentAgentID, "admin").First(&parentAgent).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", *req.ParentAgentID, "agent").First(&parentAgent).Error; err != nil {
|
||||
response.Error(c, 404, "上级代理不存在")
|
||||
return
|
||||
}
|
||||
@@ -283,7 +283,7 @@ func handleGetAgentDetail(c *gin.Context) {
|
||||
agentID := c.Param("id")
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "admin").
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").
|
||||
Preload("ParentAgent").
|
||||
First(&user).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
@@ -378,7 +378,7 @@ func handleUpdateAgent(c *gin.Context) {
|
||||
agentID := c.Param("id")
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "admin").First(&user).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
return
|
||||
}
|
||||
@@ -402,7 +402,7 @@ func handleUpdateAgent(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
var parentAgent model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", *req.ParentAgentID, "admin").First(&parentAgent).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", *req.ParentAgentID, "agent").First(&parentAgent).Error; err != nil {
|
||||
response.Error(c, 404, "上级代理不存在")
|
||||
return
|
||||
}
|
||||
@@ -446,7 +446,7 @@ func handleUpdateAgentStatus(c *gin.Context) {
|
||||
agentID := c.Param("id")
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "admin").First(&user).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
return
|
||||
}
|
||||
@@ -477,7 +477,7 @@ func handleDeleteAgent(c *gin.Context) {
|
||||
agentID := c.Param("id")
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "developer").First(&user).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
return
|
||||
}
|
||||
@@ -500,7 +500,7 @@ func handleGetAgentCards(c *gin.Context) {
|
||||
agentID := c.Param("id")
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "developer").First(&user).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
return
|
||||
}
|
||||
@@ -557,7 +557,7 @@ func handleUpdateAgentCards(c *gin.Context) {
|
||||
agentID := c.Param("id")
|
||||
|
||||
var user model.User
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "developer").First(&user).Error; err != nil {
|
||||
if err := database.DB.Where("id = ? AND role = ?", agentID, "agent").First(&user).Error; err != nil {
|
||||
response.Error(c, 404, "代理不存在")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -419,8 +419,8 @@ func handleCreateCloudVariable(c *gin.Context) {
|
||||
req.Scope = "app"
|
||||
}
|
||||
|
||||
if req.WritePermission != "developer" && req.WritePermission != "user" && req.WritePermission != "app_user" {
|
||||
req.WritePermission = "developer"
|
||||
if req.WritePermission != "admin" && req.WritePermission != "user" && req.WritePermission != "app_user" {
|
||||
req.WritePermission = "admin"
|
||||
}
|
||||
|
||||
if req.Status != "active" && req.Status != "inactive" {
|
||||
@@ -489,7 +489,7 @@ func handleUpdateCloudVariable(c *gin.Context) {
|
||||
variable.DataType = req.DataType
|
||||
}
|
||||
variable.MaxRecords = req.MaxRecords
|
||||
if req.WritePermission == "developer" || req.WritePermission == "user" || req.WritePermission == "app_user" {
|
||||
if req.WritePermission == "admin" || req.WritePermission == "user" || req.WritePermission == "app_user" {
|
||||
variable.WritePermission = req.WritePermission
|
||||
}
|
||||
variable.Description = req.Description
|
||||
@@ -571,8 +571,8 @@ func handleUploadCloudVariable(c *gin.Context) {
|
||||
scope = "app"
|
||||
}
|
||||
|
||||
if writePermission != "developer" && writePermission != "user" {
|
||||
writePermission = "developer"
|
||||
if writePermission != "admin" && writePermission != "user" {
|
||||
writePermission = "admin"
|
||||
}
|
||||
|
||||
var user model.User
|
||||
|
||||
@@ -130,7 +130,7 @@ func handleRegister(c *gin.Context) {
|
||||
req.Username, req.Email, req.Phone, req.Role, req.Type)
|
||||
|
||||
if req.Role == "" {
|
||||
req.Role = "developer"
|
||||
req.Role = "admin"
|
||||
}
|
||||
|
||||
username := req.Username
|
||||
@@ -794,7 +794,7 @@ func handleGetPublicStats(c *gin.Context) {
|
||||
var totalApps, totalUsers, totalVerifications int64
|
||||
|
||||
database.DB.Model(&model.Application{}).Count(&totalApps)
|
||||
database.DB.Model(&model.User{}).Where("role = ?", "developer").Count(&totalUsers)
|
||||
database.DB.Model(&model.User{}).Where("role = ?", "admin").Count(&totalUsers)
|
||||
database.DB.Model(&model.Card{}).Where("status = ?", "used").Count(&totalVerifications)
|
||||
|
||||
response.Success(c, gin.H{
|
||||
|
||||
@@ -70,7 +70,7 @@ func (s *AuthService) Login(username, password, agentPath string) (map[string]in
|
||||
|
||||
// Register 用户注册
|
||||
func (s *AuthService) Register(username, email, password string) error {
|
||||
return s.RegisterWithRole(username, email, "", password, "developer")
|
||||
return s.RegisterWithRole(username, email, "", password, "admin")
|
||||
}
|
||||
|
||||
// RegisterWithRole 用户注册(带角色)
|
||||
@@ -115,7 +115,7 @@ func (s *AuthService) RegisterWithRole(username, email, phone, password, role st
|
||||
}
|
||||
|
||||
if role == "" {
|
||||
role = "developer"
|
||||
role = "admin"
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
signature VARCHAR(255) DEFAULT NULL COMMENT '个性签名',
|
||||
points INT DEFAULT 0 COMMENT '积分',
|
||||
level INT DEFAULT 1 COMMENT '等级',
|
||||
role ENUM('user', 'developer', 'agent', 'admin') DEFAULT 'user' COMMENT '角色',
|
||||
role ENUM('user', 'agent', 'admin') DEFAULT 'user' COMMENT '角色',
|
||||
status ENUM('active', 'inactive', 'banned') DEFAULT 'active' COMMENT '状态',
|
||||
agent_id BIGINT UNSIGNED DEFAULT NULL COMMENT '所属代理ID',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
|
||||
@@ -7,10 +7,10 @@ import TeamSwitcher from '@/components/app-sidebar/team-switcher.vue'
|
||||
import NavFooter from '@/components/developer-sidebar/nav-footer.vue'
|
||||
|
||||
const user = reactive({
|
||||
name: '开发者',
|
||||
email: 'developer@example.com',
|
||||
avatar: '/avatars/developer.jpg',
|
||||
role: 'developer',
|
||||
name: '管理员',
|
||||
email: 'admin@example.com',
|
||||
avatar: '/avatars/admin.jpg',
|
||||
role: 'admin',
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -228,7 +228,7 @@ watch(route, () => {
|
||||
{{ t('nav.pricing') }}
|
||||
</router-link>
|
||||
|
||||
<template v-if="isLoggedIn && currentUser?.role === 'developer'">
|
||||
<template v-if="isLoggedIn && currentUser?.role === 'admin'">
|
||||
<div class="w-px h-4 bg-border mx-1" />
|
||||
|
||||
<UiDropdownMenu>
|
||||
@@ -300,79 +300,6 @@ watch(route, () => {
|
||||
</UiDropdownMenuContent>
|
||||
</UiDropdownMenu>
|
||||
</template>
|
||||
|
||||
<template v-if="isLoggedIn && currentUser?.role === 'admin'">
|
||||
<div class="w-px h-4 bg-border mx-1" />
|
||||
|
||||
<UiDropdownMenu>
|
||||
<UiDropdownMenuTrigger as-child>
|
||||
<button
|
||||
class="transition-colors hover:text-foreground/80 px-3 py-2 rounded-lg flex items-center gap-1"
|
||||
:class="isMenuActive(adminMenus.main.items) ? 'text-foreground bg-accent' : 'text-foreground/60'"
|
||||
>
|
||||
{{ adminMenus.main.title }}
|
||||
<Icon icon="lucide:chevron-down" class="h-4 w-4" />
|
||||
</button>
|
||||
</UiDropdownMenuTrigger>
|
||||
<UiDropdownMenuContent align="start" class="w-40">
|
||||
<UiDropdownMenuItem
|
||||
v-for="item in adminMenus.main.items"
|
||||
:key="item.url"
|
||||
:class="route.path === item.url ? 'bg-accent' : ''"
|
||||
@click="router.push(item.url)"
|
||||
>
|
||||
<Icon :icon="item.icon" class="mr-2 h-4 w-4" />
|
||||
{{ item.title }}
|
||||
</UiDropdownMenuItem>
|
||||
</UiDropdownMenuContent>
|
||||
</UiDropdownMenu>
|
||||
|
||||
<UiDropdownMenu>
|
||||
<UiDropdownMenuTrigger as-child>
|
||||
<button
|
||||
class="transition-colors hover:text-foreground/80 px-3 py-2 rounded-lg flex items-center gap-1"
|
||||
:class="isMenuActive(adminMenus.content.items) ? 'text-foreground bg-accent' : 'text-foreground/60'"
|
||||
>
|
||||
{{ adminMenus.content.title }}
|
||||
<Icon icon="lucide:chevron-down" class="h-4 w-4" />
|
||||
</button>
|
||||
</UiDropdownMenuTrigger>
|
||||
<UiDropdownMenuContent align="start" class="w-40">
|
||||
<UiDropdownMenuItem
|
||||
v-for="item in adminMenus.content.items"
|
||||
:key="item.url"
|
||||
:class="route.path === item.url ? 'bg-accent' : ''"
|
||||
@click="router.push(item.url)"
|
||||
>
|
||||
<Icon :icon="item.icon" class="mr-2 h-4 w-4" />
|
||||
{{ item.title }}
|
||||
</UiDropdownMenuItem>
|
||||
</UiDropdownMenuContent>
|
||||
</UiDropdownMenu>
|
||||
|
||||
<UiDropdownMenu>
|
||||
<UiDropdownMenuTrigger as-child>
|
||||
<button
|
||||
class="transition-colors hover:text-foreground/80 px-3 py-2 rounded-lg flex items-center gap-1"
|
||||
:class="isMenuActive(adminMenus.system.items) ? 'text-foreground bg-accent' : 'text-foreground/60'"
|
||||
>
|
||||
{{ adminMenus.system.title }}
|
||||
<Icon icon="lucide:chevron-down" class="h-4 w-4" />
|
||||
</button>
|
||||
</UiDropdownMenuTrigger>
|
||||
<UiDropdownMenuContent align="start" class="w-40">
|
||||
<UiDropdownMenuItem
|
||||
v-for="item in adminMenus.system.items"
|
||||
:key="item.url"
|
||||
:class="route.path === item.url ? 'bg-accent' : ''"
|
||||
@click="router.push(item.url)"
|
||||
>
|
||||
<Icon :icon="item.icon" class="mr-2 h-4 w-4" />
|
||||
{{ item.title }}
|
||||
</UiDropdownMenuItem>
|
||||
</UiDropdownMenuContent>
|
||||
</UiDropdownMenu>
|
||||
</template>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -438,18 +365,14 @@ watch(route, () => {
|
||||
<Icon icon="lucide:user" class="mr-2 h-4 w-4" />
|
||||
<span>{{ t('nav.profile') }}</span>
|
||||
</UiDropdownMenuItem>
|
||||
<UiDropdownMenuItem v-if="currentUser?.role === 'developer'" @click="router.push('/developer')">
|
||||
<UiDropdownMenuItem v-if="currentUser?.role === 'admin'" @click="router.push('/developer')">
|
||||
<Icon icon="lucide:layout-dashboard" class="mr-2 h-4 w-4" />
|
||||
<span>{{ t('nav.developerDashboard') }}</span>
|
||||
</UiDropdownMenuItem>
|
||||
<UiDropdownMenuItem v-if="currentUser?.role === 'agent'" @click="router.push('/agent/dashboard')">
|
||||
<UiDropdownMenuItem v-if="currentUser?.role === 'agent'" @click="router.push('/agent')">
|
||||
<Icon icon="lucide:layout-dashboard" class="mr-2 h-4 w-4" />
|
||||
<span>{{ t('nav.agentDashboard') }}</span>
|
||||
</UiDropdownMenuItem>
|
||||
<UiDropdownMenuItem v-if="currentUser?.role === 'admin'" @click="router.push('/admin')">
|
||||
<Icon icon="lucide:shield" class="mr-2 h-4 w-4" />
|
||||
<span>{{ t('nav.adminDashboard') }}</span>
|
||||
</UiDropdownMenuItem>
|
||||
<UiDropdownMenuSeparator />
|
||||
<UiDropdownMenuItem @click="handleLogout">
|
||||
<Icon icon="lucide:log-out" class="mr-2 h-4 w-4" />
|
||||
@@ -502,7 +425,7 @@ watch(route, () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<template v-if="isLoggedIn && currentUser?.role === 'developer'">
|
||||
<template v-if="isLoggedIn && currentUser?.role === 'admin'">
|
||||
<div class="space-y-1">
|
||||
<p class="text-xs font-medium text-muted-foreground px-3 mb-2">
|
||||
{{ developerMenus.main.title }}
|
||||
@@ -551,56 +474,6 @@ watch(route, () => {
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="isLoggedIn && currentUser?.role === 'admin'">
|
||||
<div class="space-y-1">
|
||||
<p class="text-xs font-medium text-muted-foreground px-3 mb-2">
|
||||
{{ adminMenus.main.title }}
|
||||
</p>
|
||||
<button
|
||||
v-for="item in adminMenus.main.items"
|
||||
:key="item.url"
|
||||
class="w-full flex items-center gap-3 px-3 py-2 text-sm rounded-lg transition-colors"
|
||||
:class="isActive(item.url) ? 'bg-accent text-foreground' : 'text-muted-foreground hover:bg-accent hover:text-foreground'"
|
||||
@click="navigateTo(item.url)"
|
||||
>
|
||||
<Icon :icon="item.icon" class="size-4" />
|
||||
{{ item.title }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="space-y-1">
|
||||
<p class="text-xs font-medium text-muted-foreground px-3 mb-2">
|
||||
{{ adminMenus.content.title }}
|
||||
</p>
|
||||
<button
|
||||
v-for="item in adminMenus.content.items"
|
||||
:key="item.url"
|
||||
class="w-full flex items-center gap-3 px-3 py-2 text-sm rounded-lg transition-colors"
|
||||
:class="isActive(item.url) ? 'bg-accent text-foreground' : 'text-muted-foreground hover:bg-accent hover:text-foreground'"
|
||||
@click="navigateTo(item.url)"
|
||||
>
|
||||
<Icon :icon="item.icon" class="size-4" />
|
||||
{{ item.title }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="space-y-1">
|
||||
<p class="text-xs font-medium text-muted-foreground px-3 mb-2">
|
||||
{{ adminMenus.system.title }}
|
||||
</p>
|
||||
<button
|
||||
v-for="item in adminMenus.system.items"
|
||||
:key="item.url"
|
||||
class="w-full flex items-center gap-3 px-3 py-2 text-sm rounded-lg transition-colors"
|
||||
:class="isActive(item.url) ? 'bg-accent text-foreground' : 'text-muted-foreground hover:bg-accent hover:text-foreground'"
|
||||
@click="navigateTo(item.url)"
|
||||
>
|
||||
<Icon :icon="item.icon" class="size-4" />
|
||||
{{ item.title }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</nav>
|
||||
|
||||
<div v-if="!isLoggedIn" class="pt-4 border-t mt-4 space-y-2">
|
||||
|
||||
@@ -6,7 +6,9 @@ import { useRouter } from 'vue-router'
|
||||
|
||||
import NavTeam from '@/components/app-sidebar/nav-team.vue'
|
||||
import TeamSwitcher from '@/components/app-sidebar/team-switcher.vue'
|
||||
import LanguageChange from '@/components/language-change.vue'
|
||||
import ThemePopover from '@/components/custom-theme/theme-popover.vue'
|
||||
import ToggleTheme from '@/components/toggle-theme.vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -218,7 +220,9 @@ function handleLogout() {
|
||||
</template>
|
||||
</UiBreadcrumbList>
|
||||
</UiBreadcrumb>
|
||||
<div class="ml-auto">
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
<LanguageChange />
|
||||
<ToggleTheme />
|
||||
<ThemePopover />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -3,7 +3,9 @@ import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import DeveloperSidebar from '@/components/developer-sidebar/index.vue'
|
||||
import LanguageChange from '@/components/language-change.vue'
|
||||
import ThemePopover from '@/components/custom-theme/theme-popover.vue'
|
||||
import ToggleTheme from '@/components/toggle-theme.vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -91,6 +93,8 @@ const breadcrumbs = computed(() => {
|
||||
</UiBreadcrumb>
|
||||
|
||||
<div class="ml-auto flex items-center gap-2">
|
||||
<LanguageChange />
|
||||
<ToggleTheme />
|
||||
<ThemePopover />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -30,7 +30,7 @@ const form = ref({
|
||||
data_type: 'single',
|
||||
max_records: 0,
|
||||
scope: 'app',
|
||||
write_permission: 'developer',
|
||||
write_permission: 'admin',
|
||||
description: '',
|
||||
status: 'active',
|
||||
})
|
||||
@@ -61,7 +61,7 @@ async function fetchVariable() {
|
||||
data_type: variable.data_type || 'single',
|
||||
max_records: variable.max_records || 0,
|
||||
scope: variable.scope || 'app',
|
||||
write_permission: variable.write_permission || 'developer',
|
||||
write_permission: variable.write_permission || 'admin',
|
||||
description: variable.description || '',
|
||||
status: variable.status || 'active',
|
||||
}
|
||||
@@ -297,10 +297,10 @@ onMounted(async () => {
|
||||
<UiRadioGroup v-model="form.write_permission" class="grid grid-cols-1 gap-4">
|
||||
<div
|
||||
class="flex items-start gap-3 p-4 rounded-lg border cursor-pointer transition-colors"
|
||||
:class="form.write_permission === 'developer' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'developer'"
|
||||
:class="form.write_permission === 'admin' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'admin'"
|
||||
>
|
||||
<UiRadioGroupItem value="developer" class="mt-0.5" />
|
||||
<UiRadioGroupItem value="admin" class="mt-0.5" />
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon icon="lucide:lock" class="size-4 text-primary" />
|
||||
@@ -398,7 +398,7 @@ onMounted(async () => {
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">{{ t('developer.cloudVariables.create.writePermission') }}</span>
|
||||
<UiBadge variant="secondary">
|
||||
{{ form.write_permission === 'developer' ? t('developer.cloudVariables.create.developerOnly') : form.write_permission === 'app_user' ? '应用用户可写' : t('developer.cloudVariables.create.userWritable') }}
|
||||
{{ form.write_permission === 'admin' ? t('developer.cloudVariables.create.developerOnly') : form.write_permission === 'app_user' ? '应用用户可写' : t('developer.cloudVariables.create.userWritable') }}
|
||||
</UiBadge>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm items-center">
|
||||
|
||||
@@ -30,7 +30,7 @@ const form = ref({
|
||||
data_type: 'single',
|
||||
max_records: 0,
|
||||
scope: 'app',
|
||||
write_permission: 'developer',
|
||||
write_permission: 'admin',
|
||||
description: '',
|
||||
status: 'active',
|
||||
})
|
||||
@@ -391,10 +391,10 @@ onMounted(() => {
|
||||
<UiRadioGroup v-model="form.write_permission" class="grid grid-cols-1 gap-4">
|
||||
<div
|
||||
class="flex items-start gap-3 p-4 rounded-lg border cursor-pointer transition-colors"
|
||||
:class="form.write_permission === 'developer' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'developer'"
|
||||
:class="form.write_permission === 'admin' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'admin'"
|
||||
>
|
||||
<UiRadioGroupItem value="developer" class="mt-0.5" />
|
||||
<UiRadioGroupItem value="admin" class="mt-0.5" />
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon icon="lucide:lock" class="size-4 text-primary" />
|
||||
@@ -492,7 +492,7 @@ onMounted(() => {
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">{{ t('developer.cloudVariables.create.writePermission') }}</span>
|
||||
<UiBadge variant="secondary">
|
||||
{{ form.write_permission === 'developer' ? t('developer.cloudVariables.create.developerOnly') : form.write_permission === 'app_user' ? '应用用户可写' : t('developer.cloudVariables.create.userWritable') }}
|
||||
{{ form.write_permission === 'admin' ? t('developer.cloudVariables.create.developerOnly') : form.write_permission === 'app_user' ? '应用用户可写' : t('developer.cloudVariables.create.userWritable') }}
|
||||
</UiBadge>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm items-center">
|
||||
|
||||
@@ -38,9 +38,7 @@ async function handleLogin() {
|
||||
|
||||
toast.success('登录成功')
|
||||
|
||||
const isAgent = data.user.role === 'agent' || data.user.parent_agent_id
|
||||
|
||||
if (isAgent) {
|
||||
if (data.user.role === 'agent' || data.user.parent_agent_id) {
|
||||
router.push('/agent')
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -28,7 +28,7 @@ const form = ref({
|
||||
default_value: '',
|
||||
var_type: 'string',
|
||||
scope: 'app',
|
||||
write_permission: 'developer',
|
||||
write_permission: 'admin',
|
||||
description: '',
|
||||
status: 'active',
|
||||
})
|
||||
@@ -57,7 +57,7 @@ async function fetchVariable() {
|
||||
default_value: variable.default_value || '',
|
||||
var_type: variable.var_type || 'string',
|
||||
scope: variable.scope || 'app',
|
||||
write_permission: variable.write_permission || 'developer',
|
||||
write_permission: variable.write_permission || 'admin',
|
||||
description: variable.description || '',
|
||||
status: variable.status || 'active',
|
||||
}
|
||||
@@ -239,10 +239,10 @@ onMounted(async () => {
|
||||
<UiRadioGroup v-model="form.write_permission" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div
|
||||
class="flex items-start gap-3 p-4 rounded-lg border cursor-pointer transition-colors"
|
||||
:class="form.write_permission === 'developer' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'developer'"
|
||||
:class="form.write_permission === 'admin' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'admin'"
|
||||
>
|
||||
<UiRadioGroupItem value="developer" class="mt-0.5" />
|
||||
<UiRadioGroupItem value="admin" class="mt-0.5" />
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon icon="lucide:lock" class="size-4 text-primary" />
|
||||
@@ -310,7 +310,7 @@ onMounted(async () => {
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">{{ t('developer.cloudVariables.create.writePermission') }}</span>
|
||||
<UiBadge variant="secondary">
|
||||
{{ form.write_permission === 'developer' ? t('developer.cloudVariables.create.developerOnly') : t('developer.cloudVariables.create.userWritable') }}
|
||||
{{ form.write_permission === 'admin' ? t('developer.cloudVariables.create.developerOnly') : t('developer.cloudVariables.create.userWritable') }}
|
||||
</UiBadge>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm items-center">
|
||||
|
||||
@@ -30,7 +30,7 @@ const form = ref({
|
||||
data_type: 'single',
|
||||
max_records: 0,
|
||||
scope: 'app',
|
||||
write_permission: 'developer',
|
||||
write_permission: 'admin',
|
||||
description: '',
|
||||
status: 'active',
|
||||
})
|
||||
@@ -391,10 +391,10 @@ onMounted(() => {
|
||||
<UiRadioGroup v-model="form.write_permission" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div
|
||||
class="flex items-start gap-3 p-4 rounded-lg border cursor-pointer transition-colors"
|
||||
:class="form.write_permission === 'developer' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'developer'"
|
||||
:class="form.write_permission === 'admin' ? 'border-primary bg-primary/5' : 'hover:bg-accent'"
|
||||
@click="form.write_permission = 'admin'"
|
||||
>
|
||||
<UiRadioGroupItem value="developer" class="mt-0.5" />
|
||||
<UiRadioGroupItem value="admin" class="mt-0.5" />
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Icon icon="lucide:lock" class="size-4 text-primary" />
|
||||
@@ -462,7 +462,7 @@ onMounted(() => {
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-muted-foreground">{{ t('developer.cloudVariables.create.writePermission') }}</span>
|
||||
<UiBadge variant="secondary">
|
||||
{{ form.write_permission === 'developer' ? t('developer.cloudVariables.create.developerOnly') : t('developer.cloudVariables.create.userWritable') }}
|
||||
{{ form.write_permission === 'admin' ? t('developer.cloudVariables.create.developerOnly') : t('developer.cloudVariables.create.userWritable') }}
|
||||
</UiBadge>
|
||||
</div>
|
||||
<div class="flex justify-between text-sm items-center">
|
||||
|
||||
@@ -273,9 +273,8 @@ function formatNumber(num: number) {
|
||||
|
||||
function getRoleName(role: string) {
|
||||
const roles: Record<string, string> = {
|
||||
developer: '开发者',
|
||||
agent: '代理商',
|
||||
admin: '管理员',
|
||||
agent: '代理商',
|
||||
}
|
||||
return roles[role] || role
|
||||
}
|
||||
|
||||
@@ -19,10 +19,14 @@ export function createRouterGuard(router: Router) {
|
||||
const isAuthPage = to.path === '/login' || to.path === '/register'
|
||||
|
||||
if (requiresAuth && !token) {
|
||||
return '/login'
|
||||
return { path: '/login', query: { redirect: to.fullPath } }
|
||||
}
|
||||
|
||||
if (isAuthPage && token && user) {
|
||||
const redirect = (to.query.redirect as string) || ''
|
||||
if (redirect) {
|
||||
return redirect
|
||||
}
|
||||
if (user.role === 'agent' || user.parent_agent_id) {
|
||||
return '/agent'
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
path: '/developer',
|
||||
component: () => import('@/layouts/developer.vue'),
|
||||
meta: { auth: true, role: 'developer' },
|
||||
meta: { auth: true, role: 'admin' },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
|
||||
Reference in New Issue
Block a user