120 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Package router ...
 | 
						|
//
 | 
						|
// Description : router ...
 | 
						|
//
 | 
						|
// Author : go_developer@163.com<白茶清欢>
 | 
						|
//
 | 
						|
// Date : 2025-10-30 15:39
 | 
						|
package router
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"reflect"
 | 
						|
 | 
						|
	"git.zhangdeman.cn/zhangdeman/gin/logger"
 | 
						|
	"git.zhangdeman.cn/zhangdeman/gin/util"
 | 
						|
	pkgLogger "git.zhangdeman.cn/zhangdeman/logger"
 | 
						|
	"github.com/gin-gonic/gin"
 | 
						|
)
 | 
						|
 | 
						|
// GetCommonParam 获取公共参数
 | 
						|
type GetCommonParam func(ctx *gin.Context) (any, error)
 | 
						|
 | 
						|
// AddCommonParamRule 添加公共参数注入规则
 | 
						|
func (s *server) AddCommonParamRule(fieldName string, getParamFunc GetCommonParam) {
 | 
						|
	s.commonParam[fieldName] = getParamFunc
 | 
						|
}
 | 
						|
 | 
						|
// AddCommonParamRules 批量添加公共参数注入规则
 | 
						|
func (s *server) AddCommonParamRules(rules map[string]GetCommonParam) {
 | 
						|
	for fieldName, rule := range rules {
 | 
						|
		s.AddCommonParamRule(fieldName, rule)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// injectCommonParam 注入公共参数
 | 
						|
func (s *server) injectCommonParam(ctx *gin.Context, formValue any) error {
 | 
						|
	innerCtx := util.GinCtxToContext(ctx)
 | 
						|
	var (
 | 
						|
		val              any
 | 
						|
		err              error
 | 
						|
		reflectFormValue reflect.Value
 | 
						|
		reflectType      reflect.Type
 | 
						|
		ok               bool
 | 
						|
	)
 | 
						|
 | 
						|
	if reflectFormValue, ok = formValue.(reflect.Value); !ok {
 | 
						|
		reflectFormValue = reflect.ValueOf(formValue)
 | 
						|
		reflectType = reflect.TypeOf(formValue)
 | 
						|
	} else {
 | 
						|
		reflectType = reflectFormValue.Type()
 | 
						|
	}
 | 
						|
 | 
						|
	fieldTable := map[string]bool{}
 | 
						|
	fieldNum := reflectType.Elem().NumField()
 | 
						|
	for i := 0; i < fieldNum; i++ {
 | 
						|
		if reflectType.Elem().Field(i).Anonymous && // 是匿名字段, 再做一次解析
 | 
						|
			((reflectType.Elem().Field(i).Type.Kind() == reflect.Ptr && reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) || // 结构体指针
 | 
						|
				reflectType.Elem().Field(i).Type.Kind() == reflect.Struct) { // 结构体
 | 
						|
			anonymousFieldType := reflectType.Elem().Field(i).Type
 | 
						|
			if anonymousFieldType.Kind() == reflect.Ptr {
 | 
						|
				anonymousFieldType = anonymousFieldType.Elem()
 | 
						|
			}
 | 
						|
			for j := 0; j < anonymousFieldType.NumField(); j++ {
 | 
						|
				fieldTable[anonymousFieldType.Field(j).Name] = true
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			// 提取全部结构体字段
 | 
						|
			fieldTable[reflectType.Elem().Field(i).Name] = true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for fieldName, getParamFunc := range s.commonParam {
 | 
						|
		if _, ok = fieldTable[fieldName]; !ok {
 | 
						|
			// 结构体字段未配置自动注入
 | 
						|
			logger.Instance.Debug("当前结构体不包含指定字段, 忽略执行", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
						|
				"field_name": fieldName,
 | 
						|
				"struct":     reflectFormValue.Elem().Type().String(),
 | 
						|
			}).ToFieldList()...)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		fieldValue := reflectFormValue.Elem().FieldByName(fieldName)
 | 
						|
		if !fieldValue.IsZero() {
 | 
						|
			// 表单次数不为空, 说明从参数中传递, 不做覆盖填充
 | 
						|
			logger.Instance.Debug("指定字段已赋值, 不做重新覆盖填充处理, 跳过", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
						|
				"field_name":       fieldName,
 | 
						|
				"struct":           reflectFormValue.Elem().Type().String(),
 | 
						|
				"input_form_value": fieldValue.Interface(),
 | 
						|
			}).ToFieldList()...)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		if val, err = getParamFunc(ctx); nil != err {
 | 
						|
			logger.Instance.Error("获取公共结构体字段参数值失败", pkgLogger.NewLogData(innerCtx, logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
						|
				"field_name": fieldName,
 | 
						|
				"err_msg":    err.Error(),
 | 
						|
			}).ToFieldList()...)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		if !fieldValue.CanSet() {
 | 
						|
			logDataList := pkgLogger.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
						|
				"field_name": fieldName,
 | 
						|
				"field_type": fieldValue.Type().String(),
 | 
						|
			})
 | 
						|
			logger.Instance.Error("结构体字段不可设置值", logDataList.ToFieldList()...)
 | 
						|
			return errors.New(fieldName + ": 结构体字段不可设置值")
 | 
						|
		}
 | 
						|
		reflectVal := reflect.ValueOf(val)
 | 
						|
		if reflectVal.Type() != fieldValue.Type() {
 | 
						|
			logDataList := pkgLogger.NewLogData(util.GinCtxToContext(ctx), logger.RecordType, logger.CodeInjectCommonParam, map[string]any{
 | 
						|
				"field_name": fieldName,
 | 
						|
				"field_type": fieldValue.Type().String(),
 | 
						|
				"value_type": reflectVal.Type().String(),
 | 
						|
			})
 | 
						|
			logger.Instance.Error("返回数据类型与字段类型不一致", logDataList.ToFieldList()...)
 | 
						|
			return errors.New(fieldName + ": 字段自动注入, 返回数据类型与字段类型不一致")
 | 
						|
		}
 | 
						|
		// 设置值
 | 
						|
		fieldValue.Set(reflectVal)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |