package services import ( "fmt" "regexp" "server/models" "time" "github.com/beego/beego/v2/client/orm" ) // ========== 字典类型相关服务 ========== // AddDictType 添加字典类型 func AddDictType(dictType *models.DictType) (int64, error) { // 校验字典编码格式(只能包含字母、数字、下划线) matched, err := regexp.MatchString(`^[A-Za-z0-9_]+$`, dictType.DictCode) if err != nil || !matched { return 0, fmt.Errorf("字典编码格式错误,只能包含字母、数字、下划线") } 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", dictType.DictCode, dictType.TenantId).QueryRow(existType) if err == nil { return 0, fmt.Errorf("字典编码 %s 已存在", dictType.DictCode) } // 插入新字典类型 id, err := o.Insert(dictType) if err != nil { return 0, fmt.Errorf("添加字典类型失败: %v", err) } // 清除相关缓存 clearDictCache(dictType.TenantId, dictType.DictCode) return id, nil } // UpdateDictType 更新字典类型 func UpdateDictType(dictType *models.DictType) error { o := orm.NewOrm() // 获取原字典类型信息 oldType := &models.DictType{Id: dictType.Id} err := o.Read(oldType) if err != nil { return fmt.Errorf("字典类型不存在: %v", err) } // 不允许修改 dict_code(避免业务引用失效) if oldType.DictCode != dictType.DictCode { return fmt.Errorf("不允许修改字典编码") } // 更新字段(排除 dict_code) _, err = o.Update(dictType, "dict_name", "parent_id", "status", "sort", "remark", "update_by", "update_time") if err != nil { return fmt.Errorf("更新字典类型失败: %v", err) } // 清除相关缓存 clearDictCache(dictType.TenantId, dictType.DictCode) return nil } // DeleteDictType 删除字典类型(逻辑删除) func DeleteDictType(id int, tenantId int) error { o := orm.NewOrm() // 检查是否存在 dictType := &models.DictType{Id: id} err := o.Read(dictType) if err != nil { return fmt.Errorf("字典类型不存在: %v", err) } // 检查租户权限 if dictType.TenantId != tenantId { return fmt.Errorf("无权操作该字典类型") } // 检查是否关联字典项 var count int err = o.Raw("SELECT COUNT(*) FROM sys_dict_item WHERE dict_type_id = ? AND is_deleted = 0", id).QueryRow(&count) if err == nil && count > 0 { return fmt.Errorf("该字典类型下存在字典项,请先删除字典项") } // 逻辑删除 dictType.IsDeleted = 1 dictType.UpdateTime = time.Now() _, err = o.Update(dictType, "is_deleted", "update_time") if err != nil { return fmt.Errorf("删除字典类型失败: %v", err) } // 清除相关缓存 clearDictCache(dictType.TenantId, dictType.DictCode) return nil } // GetDictTypeById 根据ID获取字典类型 func GetDictTypeById(id int) (*models.DictType, error) { o := orm.NewOrm() dictType := &models.DictType{Id: id} err := o.Read(dictType) if err != nil { return nil, err } if dictType.IsDeleted == 1 { return nil, fmt.Errorf("字典类型已删除") } return dictType, nil } // GetDictTypes 获取字典类型列表 func GetDictTypes(tenantId 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) } else { // 平台用户只能看到平台字典 qs = qs.Filter("tenant_id", 0) } // 父级过滤 if parentId >= 0 { qs = qs.Filter("parent_id", parentId) } // 状态过滤 if status != nil { qs = qs.Filter("status", *status) } var dictTypes []*models.DictType _, err := qs.OrderBy("sort", "create_time").All(&dictTypes) return dictTypes, err } // ========== 字典项相关服务 ========== // AddDictItem 添加字典项 func AddDictItem(dictItem *models.DictItem) (int64, error) { o := orm.NewOrm() // 检查字典类型是否存在 dictType := &models.DictType{Id: dictItem.DictTypeId} err := o.Read(dictType) if err != nil { return 0, fmt.Errorf("字典类型不存在: %v", err) } if dictType.IsDeleted == 1 || dictType.Status == 0 { return 0, fmt.Errorf("字典类型已删除或已禁用") } // 检查同一字典类型下 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", dictItem.DictTypeId, dictItem.DictValue).QueryRow(existItem) if err == nil { return 0, fmt.Errorf("字典值 %s 已存在", dictItem.DictValue) } // 插入新字典项 id, err := o.Insert(dictItem) if err != nil { return 0, fmt.Errorf("添加字典项失败: %v", err) } // 清除相关缓存 clearDictCacheByTypeId(dictItem.DictTypeId) return id, nil } // UpdateDictItem 更新字典项 func UpdateDictItem(dictItem *models.DictItem) error { o := orm.NewOrm() // 获取原字典项信息 oldItem := &models.DictItem{Id: dictItem.Id} err := o.Read(oldItem) if err != nil { return fmt.Errorf("字典项不存在: %v", err) } // 不允许修改 dict_value(避免业务存储值与字典不匹配) if oldItem.DictValue != dictItem.DictValue { return fmt.Errorf("不允许修改字典值") } // 如果修改了 dict_type_id,需要检查新类型是否存在 if oldItem.DictTypeId != dictItem.DictTypeId { dictType := &models.DictType{Id: dictItem.DictTypeId} err = o.Read(dictType) if err != nil { return fmt.Errorf("字典类型不存在: %v", err) } } // 更新字段(排除 dict_value) _, err = o.Update(dictItem, "dict_label", "dict_type_id", "parent_id", "status", "sort", "color", "icon", "remark", "update_by", "update_time") if err != nil { return fmt.Errorf("更新字典项失败: %v", err) } // 清除相关缓存 clearDictCacheByTypeId(oldItem.DictTypeId) if oldItem.DictTypeId != dictItem.DictTypeId { clearDictCacheByTypeId(dictItem.DictTypeId) } return nil } // DeleteDictItem 删除字典项(逻辑删除) func DeleteDictItem(id int) error { o := orm.NewOrm() // 检查是否存在 dictItem := &models.DictItem{Id: id} err := o.Read(dictItem) if err != nil { return fmt.Errorf("字典项不存在: %v", err) } // 检查是否有子项 var count int err = o.Raw("SELECT COUNT(*) FROM sys_dict_item WHERE parent_id = ? AND is_deleted = 0", id).QueryRow(&count) if err == nil && count > 0 { return fmt.Errorf("该字典项下存在子项,请先删除子项") } // 逻辑删除 dictItem.IsDeleted = 1 dictItem.UpdateTime = time.Now() _, err = o.Update(dictItem, "is_deleted", "update_time") if err != nil { return fmt.Errorf("删除字典项失败: %v", err) } // 清除相关缓存 clearDictCacheByTypeId(dictItem.DictTypeId) return nil } // GetDictItemById 根据ID获取字典项 func GetDictItemById(id int) (*models.DictItem, error) { o := orm.NewOrm() dictItem := &models.DictItem{Id: id} err := o.Read(dictItem) if err != nil { return nil, err } if dictItem.IsDeleted == 1 { return nil, fmt.Errorf("字典项已删除") } return dictItem, nil } // GetDictItems 获取字典项列表 func GetDictItems(dictTypeId int, parentId *int, status *int8) ([]*models.DictItem, error) { o := orm.NewOrm() qs := o.QueryTable("sys_dict_item").Filter("is_deleted", 0).Filter("dict_type_id", dictTypeId) // 父级过滤 if parentId != nil { qs = qs.Filter("parent_id", *parentId) } // 状态过滤 if status != nil { qs = qs.Filter("status", *status) } var dictItems []*models.DictItem _, err := qs.OrderBy("sort", "create_time").All(&dictItems) return dictItems, err } // 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", 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", dictCode).QueryRow(dictType) if err != nil { return []*models.DictItem{}, nil // 返回空列表而不是错误 } } else { return []*models.DictItem{}, nil } } // 查询字典项 qs := o.QueryTable("sys_dict_item").Filter("dict_type_id", dictType.Id).Filter("is_deleted", 0) if !includeDisabled { qs = qs.Filter("status", 1) } var dictItems []*models.DictItem _, err = qs.OrderBy("sort", "create_time").All(&dictItems) if err != nil { return nil, err } return dictItems, nil } // ========== 缓存相关(简化版,实际应使用Redis) ========== // 清除字典缓存(简化实现,实际应使用Redis) func clearDictCache(tenantId int, dictCode string) { // TODO: 实现Redis缓存清除 // 格式:SYS_DICT:ITEM:{tenantId}:{dictCode} } // 根据字典类型ID清除缓存 func clearDictCacheByTypeId(dictTypeId int) { o := orm.NewOrm() dictType := &models.DictType{Id: dictTypeId} err := o.Read(dictType) if err == nil { clearDictCache(dictType.TenantId, dictType.DictCode) } } // ========== 批量操作 ========== // BatchUpdateDictItemSort 批量更新字典项排序 func BatchUpdateDictItemSort(items []struct { Id int `json:"id"` Sort int `json:"sort"` }) error { o := orm.NewOrm() for _, item := range items { dictItem := &models.DictItem{Id: item.Id} err := o.Read(dictItem) if err != nil { continue } dictItem.Sort = item.Sort dictItem.UpdateTime = time.Now() _, err = o.Update(dictItem, "sort", "update_time") if err != nil { return fmt.Errorf("更新字典项排序失败: %v", err) } } return nil }