473 lines
14 KiB
Go
473 lines
14 KiB
Go
package system
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strconv"
|
|
|
|
"kra/internal/biz/system"
|
|
"kra/internal/data/model"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type dictionaryRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewDictionaryRepo 创建字典仓储
|
|
func NewDictionaryRepo(db *gorm.DB) system.DictionaryRepo {
|
|
return &dictionaryRepo{db: db}
|
|
}
|
|
|
|
func (r *dictionaryRepo) Create(ctx context.Context, dict *system.Dictionary) error {
|
|
m := toModelDictionary(dict)
|
|
if err := r.db.WithContext(ctx).Create(m).Error; err != nil {
|
|
return err
|
|
}
|
|
dict.ID = uint(m.ID)
|
|
return nil
|
|
}
|
|
|
|
func (r *dictionaryRepo) Update(ctx context.Context, dict *system.Dictionary) error {
|
|
updates := map[string]interface{}{
|
|
"name": dict.Name,
|
|
"type": dict.Type,
|
|
"status": dict.Status,
|
|
"desc": dict.Desc,
|
|
"parent_id": dict.ParentID,
|
|
}
|
|
return r.db.WithContext(ctx).Model(&model.SysDictionary{}).Where("id = ?", dict.ID).Updates(updates).Error
|
|
}
|
|
|
|
func (r *dictionaryRepo) Delete(ctx context.Context, id uint) error {
|
|
return r.db.WithContext(ctx).Delete(&model.SysDictionary{}, id).Error
|
|
}
|
|
|
|
func (r *dictionaryRepo) FindByID(ctx context.Context, id uint) (*system.Dictionary, error) {
|
|
var m model.SysDictionary
|
|
if err := r.db.WithContext(ctx).First(&m, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return toBizDictionary(&m), nil
|
|
}
|
|
|
|
func (r *dictionaryRepo) FindByType(ctx context.Context, typ string) (*system.Dictionary, error) {
|
|
var m model.SysDictionary
|
|
if err := r.db.WithContext(ctx).Where("type = ?", typ).First(&m).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return toBizDictionary(&m), nil
|
|
}
|
|
|
|
func (r *dictionaryRepo) GetByTypeOrID(ctx context.Context, typ string, id uint, status *bool) (*system.Dictionary, error) {
|
|
flag := true
|
|
if status != nil {
|
|
flag = *status
|
|
}
|
|
var m model.SysDictionary
|
|
db := r.db.WithContext(ctx).Where("(type = ? OR id = ?) AND status = ?", typ, id, flag)
|
|
if err := db.First(&m).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
dict := toBizDictionary(&m)
|
|
// 加载详情
|
|
var details []model.SysDictionaryDetail
|
|
r.db.WithContext(ctx).Where("sys_dictionary_id = ? AND status = ?", m.ID, true).Order("sort").Find(&details)
|
|
// 详情在service层处理
|
|
return dict, nil
|
|
}
|
|
|
|
func (r *dictionaryRepo) List(ctx context.Context, name string) ([]*system.Dictionary, error) {
|
|
db := r.db.WithContext(ctx).Model(&model.SysDictionary{})
|
|
if name != "" {
|
|
db = db.Where("name LIKE ? OR type LIKE ?", "%"+name+"%", "%"+name+"%")
|
|
}
|
|
// 预加载子字典
|
|
db = db.Preload("Children")
|
|
var list []model.SysDictionary
|
|
if err := db.Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]*system.Dictionary, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionary(&m)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *dictionaryRepo) CheckCircularReference(ctx context.Context, currentID, parentID uint) error {
|
|
if currentID == parentID {
|
|
return errors.New("不能将字典设置为自己的父级")
|
|
}
|
|
var parent model.SysDictionary
|
|
if err := r.db.WithContext(ctx).Where("id = ?", parentID).First(&parent).Error; err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
if parent.ParentID != 0 {
|
|
return r.CheckCircularReference(ctx, currentID, uint(parent.ParentID))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type dictionaryDetailRepo struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewDictionaryDetailRepo 创建字典详情仓储
|
|
func NewDictionaryDetailRepo(db *gorm.DB) system.DictionaryDetailRepo {
|
|
return &dictionaryDetailRepo{db: db}
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) Create(ctx context.Context, detail *system.DictionaryDetail) error {
|
|
m := toModelDictionaryDetail(detail)
|
|
if err := r.db.WithContext(ctx).Create(m).Error; err != nil {
|
|
return err
|
|
}
|
|
detail.ID = uint(m.ID)
|
|
return nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) Update(ctx context.Context, detail *system.DictionaryDetail) error {
|
|
m := toModelDictionaryDetail(detail)
|
|
return r.db.WithContext(ctx).Save(m).Error
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) Delete(ctx context.Context, id uint) error {
|
|
return r.db.WithContext(ctx).Delete(&model.SysDictionaryDetail{}, id).Error
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) FindByID(ctx context.Context, id uint) (*system.DictionaryDetail, error) {
|
|
var m model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).First(&m, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return toBizDictionaryDetail(&m), nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) List(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*system.DictionaryDetail, int64, error) {
|
|
db := r.db.WithContext(ctx).Model(&model.SysDictionaryDetail{})
|
|
if v, ok := filters["label"]; ok && v != "" {
|
|
db = db.Where("label LIKE ?", "%"+v.(string)+"%")
|
|
}
|
|
if v, ok := filters["value"]; ok && v != "" {
|
|
db = db.Where("value = ?", v)
|
|
}
|
|
if v, ok := filters["status"]; ok {
|
|
db = db.Where("status = ?", v)
|
|
}
|
|
if v, ok := filters["sys_dictionary_id"]; ok && v.(uint) != 0 {
|
|
db = db.Where("sys_dictionary_id = ?", v)
|
|
}
|
|
if v, ok := filters["parent_id"]; ok {
|
|
db = db.Where("parent_id = ?", v)
|
|
}
|
|
if v, ok := filters["level"]; ok {
|
|
db = db.Where("level = ?", v)
|
|
}
|
|
|
|
var total int64
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
offset := (page - 1) * pageSize
|
|
var list []model.SysDictionaryDetail
|
|
if err := db.Offset(offset).Limit(pageSize).Order("sort").Order("id").Find(&list).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
result := make([]*system.DictionaryDetail, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionaryDetail(&m)
|
|
}
|
|
return result, total, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetListByDictionaryID(ctx context.Context, dictionaryID uint) ([]*system.DictionaryDetail, error) {
|
|
var list []model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Where("sys_dictionary_id = ?", dictionaryID).Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]*system.DictionaryDetail, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionaryDetail(&m)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetTreeList(ctx context.Context, dictionaryID uint) ([]*system.DictionaryDetail, error) {
|
|
var list []model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Where("sys_dictionary_id = ? AND parent_id IS NULL", dictionaryID).Order("sort").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]*system.DictionaryDetail, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionaryDetail(&m)
|
|
r.setDisabled(result[i])
|
|
if err := r.loadChildren(ctx, result[i]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) loadChildren(ctx context.Context, detail *system.DictionaryDetail) error {
|
|
var children []model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Where("parent_id = ?", detail.ID).Order("sort").Find(&children).Error; err != nil {
|
|
return err
|
|
}
|
|
for _, m := range children {
|
|
child := toBizDictionaryDetail(&m)
|
|
r.setDisabled(child)
|
|
if err := r.loadChildren(ctx, child); err != nil {
|
|
return err
|
|
}
|
|
detail.Children = append(detail.Children, child)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) setDisabled(detail *system.DictionaryDetail) {
|
|
if detail.Status != nil {
|
|
detail.Disabled = !*detail.Status
|
|
} else {
|
|
detail.Disabled = false
|
|
}
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]*system.DictionaryDetail, error) {
|
|
db := r.db.WithContext(ctx).Model(&model.SysDictionaryDetail{}).Where("sys_dictionary_id = ?", dictionaryID)
|
|
if parentID != nil {
|
|
db = db.Where("parent_id = ?", *parentID)
|
|
} else {
|
|
db = db.Where("parent_id IS NULL")
|
|
}
|
|
var list []model.SysDictionaryDetail
|
|
if err := db.Order("sort").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]*system.DictionaryDetail, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionaryDetail(&m)
|
|
r.setDisabled(result[i])
|
|
if includeChildren {
|
|
if err := r.loadChildren(ctx, result[i]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetByDictionaryIDAndValue(ctx context.Context, dictionaryID uint, value string) (*system.DictionaryDetail, error) {
|
|
var m model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Where("sys_dictionary_id = ? AND value = ?", dictionaryID, value).First(&m).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return toBizDictionaryDetail(&m), nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetByTypeAndValue(ctx context.Context, typ, value string) (*system.DictionaryDetail, error) {
|
|
var m model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Model(&model.SysDictionaryDetail{}).
|
|
Joins("JOIN sys_dictionaries ON sys_dictionaries.id = sys_dictionary_details.sys_dictionary_id").
|
|
Where("sys_dictionaries.type = ? AND sys_dictionary_details.value = ?", typ, value).
|
|
First(&m).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return toBizDictionaryDetail(&m), nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetTreeListByType(ctx context.Context, typ string) ([]*system.DictionaryDetail, error) {
|
|
var list []model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Model(&model.SysDictionaryDetail{}).
|
|
Joins("JOIN sys_dictionaries ON sys_dictionaries.id = sys_dictionary_details.sys_dictionary_id").
|
|
Where("sys_dictionaries.type = ? AND sys_dictionary_details.parent_id IS NULL", typ).
|
|
Order("sys_dictionary_details.sort").
|
|
Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]*system.DictionaryDetail, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionaryDetail(&m)
|
|
r.setDisabled(result[i])
|
|
if err := r.loadChildren(ctx, result[i]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetListByType(ctx context.Context, typ string) ([]*system.DictionaryDetail, error) {
|
|
var list []model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Model(&model.SysDictionaryDetail{}).
|
|
Joins("JOIN sys_dictionaries ON sys_dictionaries.id = sys_dictionary_details.sys_dictionary_id").
|
|
Where("sys_dictionaries.type = ?", typ).
|
|
Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]*system.DictionaryDetail, len(list))
|
|
for i, m := range list {
|
|
result[i] = toBizDictionaryDetail(&m)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) HasChildren(ctx context.Context, id uint) (bool, error) {
|
|
var count int64
|
|
if err := r.db.WithContext(ctx).Model(&model.SysDictionaryDetail{}).Where("parent_id = ?", id).Count(&count).Error; err != nil {
|
|
return false, err
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) CheckCircularReference(ctx context.Context, id, parentID uint) bool {
|
|
if id == parentID {
|
|
return true
|
|
}
|
|
var parent model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).First(&parent, parentID).Error; err != nil {
|
|
return false
|
|
}
|
|
if parent.ParentID == 0 {
|
|
return false
|
|
}
|
|
return r.CheckCircularReference(ctx, id, uint(parent.ParentID))
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) UpdateChildrenLevelAndPath(ctx context.Context, parentID uint) error {
|
|
var children []model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).Where("parent_id = ?", parentID).Find(&children).Error; err != nil {
|
|
return err
|
|
}
|
|
var parent model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).First(&parent, parentID).Error; err != nil {
|
|
return err
|
|
}
|
|
for _, child := range children {
|
|
child.Level = parent.Level + 1
|
|
if parent.Path == "" {
|
|
child.Path = strconv.Itoa(int(parent.ID))
|
|
} else {
|
|
child.Path = parent.Path + "," + strconv.Itoa(int(parent.ID))
|
|
}
|
|
if err := r.db.WithContext(ctx).Save(&child).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := r.UpdateChildrenLevelAndPath(ctx, uint(child.ID)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) GetPath(ctx context.Context, id uint) ([]*system.DictionaryDetail, error) {
|
|
var m model.SysDictionaryDetail
|
|
if err := r.db.WithContext(ctx).First(&m, id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
detail := toBizDictionaryDetail(&m)
|
|
path := []*system.DictionaryDetail{detail}
|
|
if m.ParentID != 0 {
|
|
parentPath, err := r.GetPath(ctx, uint(m.ParentID))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
path = append(parentPath, path...)
|
|
}
|
|
return path, nil
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) DeleteByDictionaryID(ctx context.Context, dictionaryID uint) error {
|
|
return r.db.WithContext(ctx).Where("sys_dictionary_id = ?", dictionaryID).Delete(&model.SysDictionaryDetail{}).Error
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) BatchCreate(ctx context.Context, details []*system.DictionaryDetail) error {
|
|
models := make([]*model.SysDictionaryDetail, len(details))
|
|
for i, d := range details {
|
|
models[i] = toModelDictionaryDetail(d)
|
|
}
|
|
return r.db.WithContext(ctx).Create(&models).Error
|
|
}
|
|
|
|
func (r *dictionaryDetailRepo) BatchUpdateParentID(ctx context.Context, idMap map[uint]uint) error {
|
|
// idMap: oldID -> newID
|
|
// 这里需要根据实际导入逻辑处理
|
|
return nil
|
|
}
|
|
|
|
// 转换函数
|
|
func toModelDictionary(d *system.Dictionary) *model.SysDictionary {
|
|
m := &model.SysDictionary{
|
|
ID: int64(d.ID),
|
|
Name: d.Name,
|
|
Type: d.Type,
|
|
Desc: d.Desc,
|
|
}
|
|
if d.Status != nil {
|
|
m.Status = *d.Status
|
|
}
|
|
if d.ParentID != nil {
|
|
m.ParentID = int64(*d.ParentID)
|
|
}
|
|
return m
|
|
}
|
|
|
|
func toBizDictionary(m *model.SysDictionary) *system.Dictionary {
|
|
d := &system.Dictionary{
|
|
ID: uint(m.ID),
|
|
Name: m.Name,
|
|
Type: m.Type,
|
|
Status: &m.Status,
|
|
Desc: m.Desc,
|
|
}
|
|
if m.ParentID != 0 {
|
|
pid := uint(m.ParentID)
|
|
d.ParentID = &pid
|
|
}
|
|
return d
|
|
}
|
|
|
|
func toModelDictionaryDetail(d *system.DictionaryDetail) *model.SysDictionaryDetail {
|
|
m := &model.SysDictionaryDetail{
|
|
ID: int64(d.ID),
|
|
Label: d.Label,
|
|
Value: d.Value,
|
|
Extend: d.Extend,
|
|
Sort: int64(d.Sort),
|
|
SysDictionaryID: int64(d.SysDictionaryID),
|
|
Level: int64(d.Level),
|
|
Path: d.Path,
|
|
}
|
|
if d.Status != nil {
|
|
m.Status = *d.Status
|
|
}
|
|
if d.ParentID != nil {
|
|
m.ParentID = int64(*d.ParentID)
|
|
}
|
|
return m
|
|
}
|
|
|
|
func toBizDictionaryDetail(m *model.SysDictionaryDetail) *system.DictionaryDetail {
|
|
d := &system.DictionaryDetail{
|
|
ID: uint(m.ID),
|
|
Label: m.Label,
|
|
Value: m.Value,
|
|
Extend: m.Extend,
|
|
Status: &m.Status,
|
|
Sort: int(m.Sort),
|
|
SysDictionaryID: uint(m.SysDictionaryID),
|
|
Level: int(m.Level),
|
|
Path: m.Path,
|
|
}
|
|
if m.ParentID != 0 {
|
|
pid := uint(m.ParentID)
|
|
d.ParentID = &pid
|
|
}
|
|
return d
|
|
}
|