From ad4cc5408de190b460d4dce3d929ebdbca97cc1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=89=AB=E5=9C=B0=E5=83=A7?= <357099073@qq.com> Date: Tue, 11 Nov 2025 20:25:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=97=E5=85=B8=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pc/src/api/dict.js | 10 ++++- .../system/dict/components/DictTypeEdit.vue | 19 +++++++++ pc/src/views/system/dict/index.vue | 7 ++++ server/controllers/dict.go | 34 ++++++++++++++-- server/models/dict.go | 1 + server/services/dict.go | 40 +++++++++++-------- server/services/user.go | 21 ++++++++++ 7 files changed, 109 insertions(+), 23 deletions(-) diff --git a/pc/src/api/dict.js b/pc/src/api/dict.js index c67a952..ec1ae7b 100644 --- a/pc/src/api/dict.js +++ b/pc/src/api/dict.js @@ -22,7 +22,10 @@ export function addDictType(data) { return request({ url: '/api/dict/types', method: 'post', - data + data: { + ...data, + is_global: data.is_global !== undefined ? data.is_global : 0 + } }) } @@ -31,7 +34,10 @@ export function updateDictType(id, data) { return request({ url: `/api/dict/types/${id}`, method: 'put', - data + data: { + ...data, + is_global: data.is_global !== undefined ? data.is_global : 0 + } }) } diff --git a/pc/src/views/system/dict/components/DictTypeEdit.vue b/pc/src/views/system/dict/components/DictTypeEdit.vue index 9305a49..4db050f 100644 --- a/pc/src/views/system/dict/components/DictTypeEdit.vue +++ b/pc/src/views/system/dict/components/DictTypeEdit.vue @@ -32,6 +32,13 @@ 禁用 + + + + + +
是:所有租户可见;否:仅租户内部可见
+
(); + const authStore = useAuthStore(); // 已移除父级选择 // 判断是否为编辑模式 @@ -94,12 +103,19 @@ return !!(props.dictType && props.dictType.id); }); + // 判断是否应该显示全局展示选项(只有 system_admin 和 admin 角色才能看到) + const shouldShowGlobalOption = computed(() => { + const roleCode = authStore.user.role_code; + return roleCode === 'system_admin' || roleCode === 'admin'; + }); + // 表单数据 const dictTypeForm = reactive({ id: null as number | null, dict_code: '', dict_name: '', status: 1, + is_global: 0, sort: 0, remark: '', }); @@ -140,6 +156,7 @@ dictTypeForm.dict_code = newDictType.dict_code || ''; dictTypeForm.dict_name = newDictType.dict_name || ''; dictTypeForm.status = newDictType.status !== undefined ? newDictType.status : 1; + dictTypeForm.is_global = newDictType.is_global !== undefined ? newDictType.is_global : 0; dictTypeForm.sort = newDictType.sort || 0; dictTypeForm.remark = newDictType.remark || ''; } else { @@ -157,6 +174,7 @@ dictTypeForm.dict_code = ''; dictTypeForm.dict_name = ''; dictTypeForm.status = 1; + dictTypeForm.is_global = 0; dictTypeForm.sort = 0; dictTypeForm.remark = ''; dictTypeFormRef.value?.clearValidate(); @@ -184,6 +202,7 @@ dict_code: dictTypeForm.dict_code, dict_name: dictTypeForm.dict_name, status: dictTypeForm.status, + is_global: dictTypeForm.is_global, sort: dictTypeForm.sort, remark: dictTypeForm.remark || '', }; diff --git a/pc/src/views/system/dict/index.vue b/pc/src/views/system/dict/index.vue index 0c336fa..13d41fe 100644 --- a/pc/src/views/system/dict/index.vue +++ b/pc/src/views/system/dict/index.vue @@ -60,6 +60,13 @@ + + + diff --git a/server/controllers/dict.go b/server/controllers/dict.go index 9d0143a..3cde5cf 100644 --- a/server/controllers/dict.go +++ b/server/controllers/dict.go @@ -25,9 +25,18 @@ func (c *DictController) GetDictTypes() { } } + // 获取用户ID + userIdData := c.Ctx.Input.GetData("userId") + userId := 0 + if userIdData != nil { + if uid, ok := userIdData.(int); ok { + userId = uid + } + } + parentId, _ := c.GetInt("parent_id", -1) statusStr := c.GetString("status") - + var status *int8 if statusStr != "" { s, _ := strconv.ParseInt(statusStr, 10, 8) @@ -35,7 +44,7 @@ func (c *DictController) GetDictTypes() { status = &statusVal } - dictTypes, err := services.GetDictTypes(tenantId, parentId, status) + dictTypes, err := services.GetDictTypes(tenantId, userId, parentId, status) if err != nil { c.Data["json"] = map[string]interface{}{ "success": false, @@ -109,6 +118,13 @@ func (c *DictController) AddDictType() { username = u } } + userIdData := c.Ctx.Input.GetData("userId") + userId := 0 + if userIdData != nil { + if uid, ok := userIdData.(int); ok { + userId = uid + } + } // 设置租户ID和创建人 dictType.TenantId = tenantId @@ -117,6 +133,17 @@ func (c *DictController) AddDictType() { dictType.Status = 1 // 默认启用 } + // 根据用户角色设置是否全局展示 + // system_admin 和 admin 角色默认是全局,其他角色默认是租户私有 + dictType.IsGlobal = 0 // 默认为租户私有 + if userId > 0 { + // 获取用户的角色信息 + roleCode, err := services.GetUserRoleCode(userId) + if err == nil && (roleCode == "system_admin" || roleCode == "admin") { + dictType.IsGlobal = 1 // system_admin 和 admin 角色默认全局 + } + } + id, err := services.AddDictType(&dictType) if err != nil { c.Data["json"] = map[string]interface{}{ @@ -240,7 +267,7 @@ func (c *DictController) GetDictItems() { parentIdStr := c.GetString("parent_id") statusStr := c.GetString("status") - + var parentId *int if parentIdStr != "" { pid, _ := strconv.Atoi(parentIdStr) @@ -508,4 +535,3 @@ func (c *DictController) BatchUpdateDictItemSort() { } c.ServeJSON() } - diff --git a/server/models/dict.go b/server/models/dict.go index 3879e4a..d638e8b 100644 --- a/server/models/dict.go +++ b/server/models/dict.go @@ -12,6 +12,7 @@ type DictType struct { DictName string `orm:"column(dict_name);size(100)" json:"dict_name"` // 字典名称 ParentId int `orm:"column(parent_id);default(0)" json:"parent_id"` // 父级字典ID(支持多级) Status int8 `orm:"column(status);default(1)" json:"status"` // 0-禁用,1-启用 + IsGlobal int8 `orm:"column(is_global);default(0)" json:"is_global"` // 0-租户私有,1-全局展示 Sort int `orm:"column(sort);default(0)" json:"sort"` // 排序号 Remark string `orm:"column(remark);size(500);null" json:"remark"` // 备注 CreateBy string `orm:"column(create_by);size(50);null" json:"create_by"` diff --git a/server/services/dict.go b/server/services/dict.go index c52f333..b7f39cb 100644 --- a/server/services/dict.go +++ b/server/services/dict.go @@ -20,10 +20,10 @@ func AddDictType(dictType *models.DictType) (int64, error) { } o := orm.NewOrm() - + // 检查字典编码是否已存在(同一租户下唯一) existType := &models.DictType{} - err = o.Raw("SELECT id FROM sys_dict_type WHERE dict_code = ? AND tenant_id = ? AND is_deleted = 0", + err = o.Raw("SELECT id FROM sys_dict_type WHERE dict_code = ? AND tenant_id = ? AND is_deleted = 0", dictType.DictCode, dictType.TenantId).QueryRow(existType) if err == nil { return 0, fmt.Errorf("字典编码 %s 已存在", dictType.DictCode) @@ -44,7 +44,7 @@ func AddDictType(dictType *models.DictType) (int64, error) { // UpdateDictType 更新字典类型 func UpdateDictType(dictType *models.DictType) error { o := orm.NewOrm() - + // 获取原字典类型信息 oldType := &models.DictType{Id: dictType.Id} err := o.Read(oldType) @@ -58,7 +58,7 @@ func UpdateDictType(dictType *models.DictType) error { } // 更新字段(排除 dict_code) - _, err = o.Update(dictType, "dict_name", "parent_id", "status", "sort", "remark", "update_by", "update_time") + _, err = o.Update(dictType, "dict_name", "parent_id", "status", "is_global", "sort", "remark", "update_by", "update_time") if err != nil { return fmt.Errorf("更新字典类型失败: %v", err) } @@ -72,7 +72,7 @@ func UpdateDictType(dictType *models.DictType) error { // DeleteDictType 删除字典类型(逻辑删除) func DeleteDictType(id int, tenantId int) error { o := orm.NewOrm() - + // 检查是否存在 dictType := &models.DictType{Id: id} err := o.Read(dictType) @@ -121,14 +121,21 @@ func GetDictTypeById(id int) (*models.DictType, error) { } // GetDictTypes 获取字典类型列表 -func GetDictTypes(tenantId int, parentId int, status *int8) ([]*models.DictType, error) { +func GetDictTypes(tenantId int, userId int, parentId int, status *int8) ([]*models.DictType, error) { o := orm.NewOrm() qs := o.QueryTable("sys_dict_type").Filter("is_deleted", 0) // 租户过滤:0表示平台字典,>0表示租户字典 if tenantId > 0 { - // 租户用户只能看到自己的字典和平台字典 - qs = qs.Filter("tenant_id__in", 0, tenantId) + // 租户用户需要根据角色判断是否可以看到私有字典 + roleCode, err := GetUserRoleCode(userId) + if err != nil || (roleCode != "system_admin" && roleCode != "admin") { + // 非admin用户只能看到全局字典和自己租户的全局字典 + qs = qs.Filter("is_global", 1) + } else { + // admin用户可以看到自己租户的所有字典和全局字典 + qs = qs.Filter("tenant_id__in", 0, tenantId) + } } else { // 平台用户只能看到平台字典 qs = qs.Filter("tenant_id", 0) @@ -154,7 +161,7 @@ func GetDictTypes(tenantId int, parentId int, status *int8) ([]*models.DictType, // AddDictItem 添加字典项 func AddDictItem(dictItem *models.DictItem) (int64, error) { o := orm.NewOrm() - + // 检查字典类型是否存在 dictType := &models.DictType{Id: dictItem.DictTypeId} err := o.Read(dictType) @@ -167,7 +174,7 @@ func AddDictItem(dictItem *models.DictItem) (int64, error) { // 检查同一字典类型下 dict_value 是否已存在 existItem := &models.DictItem{} - err = o.Raw("SELECT id FROM sys_dict_item WHERE dict_type_id = ? AND dict_value = ? AND is_deleted = 0", + err = o.Raw("SELECT id FROM sys_dict_item WHERE dict_type_id = ? AND dict_value = ? AND is_deleted = 0", dictItem.DictTypeId, dictItem.DictValue).QueryRow(existItem) if err == nil { return 0, fmt.Errorf("字典值 %s 已存在", dictItem.DictValue) @@ -188,7 +195,7 @@ func AddDictItem(dictItem *models.DictItem) (int64, error) { // UpdateDictItem 更新字典项 func UpdateDictItem(dictItem *models.DictItem) error { o := orm.NewOrm() - + // 获取原字典项信息 oldItem := &models.DictItem{Id: dictItem.Id} err := o.Read(oldItem) @@ -228,7 +235,7 @@ func UpdateDictItem(dictItem *models.DictItem) error { // DeleteDictItem 删除字典项(逻辑删除) func DeleteDictItem(id int) error { o := orm.NewOrm() - + // 检查是否存在 dictItem := &models.DictItem{Id: id} err := o.Read(dictItem) @@ -294,15 +301,15 @@ func GetDictItems(dictTypeId int, parentId *int, status *int8) ([]*models.DictIt // GetDictItemsByCode 根据字典编码获取字典项列表(支持缓存) func GetDictItemsByCode(dictCode string, tenantId int, includeDisabled bool) ([]*models.DictItem, error) { o := orm.NewOrm() - + // 先查询字典类型 dictType := &models.DictType{} - err := o.Raw("SELECT * FROM sys_dict_type WHERE dict_code = ? AND tenant_id = ? AND is_deleted = 0 AND status = 1", + err := o.Raw("SELECT * FROM sys_dict_type WHERE dict_code = ? AND tenant_id = ? AND is_deleted = 0 AND status = 1", dictCode, tenantId).QueryRow(dictType) if err != nil { // 如果租户字典不存在,尝试查询平台字典 if tenantId > 0 { - err = o.Raw("SELECT * FROM sys_dict_type WHERE dict_code = ? AND tenant_id = 0 AND is_deleted = 0 AND status = 1", + err = o.Raw("SELECT * FROM sys_dict_type WHERE dict_code = ? AND tenant_id = 0 AND is_deleted = 0 AND status = 1", dictCode).QueryRow(dictType) if err != nil { return []*models.DictItem{}, nil // 返回空列表而不是错误 @@ -353,7 +360,7 @@ func BatchUpdateDictItemSort(items []struct { Sort int `json:"sort"` }) error { o := orm.NewOrm() - + for _, item := range items { dictItem := &models.DictItem{Id: item.Id} err := o.Read(dictItem) @@ -370,4 +377,3 @@ func BatchUpdateDictItemSort(items []struct { return nil } - diff --git a/server/services/user.go b/server/services/user.go index 8355021..5d539ec 100644 --- a/server/services/user.go +++ b/server/services/user.go @@ -317,3 +317,24 @@ func ChangePassword(username, oldPassword, newPassword string, tenantId int) err return err } +// GetUserRoleCode 根据用户ID获取用户的角色代码 +func GetUserRoleCode(userId int) (string, error) { + o := orm.NewOrm() + user := &models.User{Id: userId} + err := o.Read(user) + if err != nil { + return "", err + } + + // 根据用户的role字段获取角色信息 + if user.Role <= 0 { + return "", errors.New("用户未设置角色") + } + + role, err := models.GetRoleById(user.Role) + if err != nil { + return "", err + } + + return role.RoleCode, nil +}