package services import ( "reflect" "strings" "tyapi-server/internal/domains/api/dto" ) // FormField 表单字段配置 type FormField struct { Name string `json:"name"` Label string `json:"label"` Type string `json:"type"` Required bool `json:"required"` Validation string `json:"validation"` Description string `json:"description"` Example string `json:"example"` Placeholder string `json:"placeholder"` } // FormConfig 表单配置 type FormConfig struct { ApiCode string `json:"api_code"` Fields []FormField `json:"fields"` } // FormConfigService 表单配置服务接口 type FormConfigService interface { GetFormConfig(apiCode string) (*FormConfig, error) } // FormConfigServiceImpl 表单配置服务实现 type FormConfigServiceImpl struct{} // NewFormConfigService 创建表单配置服务 func NewFormConfigService() FormConfigService { return &FormConfigServiceImpl{} } // GetFormConfig 获取指定API的表单配置 func (s *FormConfigServiceImpl) GetFormConfig(apiCode string) (*FormConfig, error) { // 根据API代码获取对应的DTO结构体 dtoStruct := s.getDTOStruct(apiCode) if dtoStruct == nil { return nil, nil } // 通过反射解析结构体字段 fields := s.parseDTOFields(dtoStruct) config := &FormConfig{ ApiCode: apiCode, Fields: fields, } return config, nil } // getDTOStruct 根据API代码获取对应的DTO结构体 func (s *FormConfigServiceImpl) getDTOStruct(apiCode string) interface{} { // 建立API代码到DTO结构体的映射 dtoMap := map[string]interface{}{ "IVYZ9363": &dto.IVYZ9363Req{}, "IVYZ385E": &dto.IVYZ385EReq{}, "IVYZ5733": &dto.IVYZ5733Req{}, "FLXG3D56": &dto.FLXG3D56Req{}, "FLXG75FE": &dto.FLXG75FEReq{}, "FLXG0V3B": &dto.FLXG0V3BReq{}, "FLXG0V4B": &dto.FLXG0V4BReq{}, "FLXG54F5": &dto.FLXG54F5Req{}, "FLXG162A": &dto.FLXG162AReq{}, "FLXG0687": &dto.FLXG0687Req{}, "FLXGBC21": &dto.FLXGBC21Req{}, "FLXG970F": &dto.FLXG970FReq{}, "FLXG5876": &dto.FLXG5876Req{}, "FLXG9687": &dto.FLXG9687Req{}, "FLXGC9D1": &dto.FLXGC9D1Req{}, "FLXGCA3D": &dto.FLXGCA3DReq{}, "FLXGDEC7": &dto.FLXGDEC7Req{}, "JRZQ0A03": &dto.JRZQ0A03Req{}, "JRZQ4AA8": &dto.JRZQ4AA8Req{}, "JRZQ8203": &dto.JRZQ8203Req{}, "JRZQDBCE": &dto.JRZQDBCEReq{}, "QYGL2ACD": &dto.QYGL2ACDReq{}, "QYGL6F2D": &dto.QYGL6F2DReq{}, "QYGL45BD": &dto.QYGL45BDReq{}, "QYGL8261": &dto.QYGL8261Req{}, "QYGL8271": &dto.QYGL8271Req{}, "QYGLB4C0": &dto.QYGLB4C0Req{}, "QYGL23T7": &dto.QYGL23T7Req{}, "QYGL5A3C": &dto.QYGL5A3CReq{}, "QYGL8B4D": &dto.QYGL8B4DReq{}, "QYGL9E2F": &dto.QYGL9E2FReq{}, "QYGL7C1A": &dto.QYGL7C1AReq{}, "QYGL3F8E": &dto.QYGL3F8EReq{}, "YYSY4B37": &dto.YYSY4B37Req{}, "YYSY4B21": &dto.YYSY4B21Req{}, "YYSY6F2E": &dto.YYSY6F2EReq{}, "YYSY09CD": &dto.YYSY09CDReq{}, "IVYZ0b03": &dto.IVYZ0b03Req{}, "YYSYBE08": &dto.YYSYBE08Req{}, "YYSYD50F": &dto.YYSYD50FReq{}, "YYSYF7DB": &dto.YYSYF7DBReq{}, "IVYZ9A2B": &dto.IVYZ9A2BReq{}, "IVYZ7F2A": &dto.IVYZ7F2AReq{}, "IVYZ4E8B": &dto.IVYZ4E8BReq{}, "IVYZ1C9D": &dto.IVYZ1C9DReq{}, "IVYZGZ08": &dto.IVYZGZ08Req{}, "FLXG8A3F": &dto.FLXG8A3FReq{}, "FLXG5B2E": &dto.FLXG5B2EReq{}, "COMB298Y": &dto.COMB298YReq{}, "COMB86PM": &dto.COMB86PMReq{}, "QCXG7A2B": &dto.QCXG7A2BReq{}, "COMENT01": &dto.COMENT01Req{}, "JRZQ09J8": &dto.JRZQ09J8Req{}, "FLXGDEA8": &dto.FLXGDEA8Req{}, "FLXGDEA9": &dto.FLXGDEA9Req{}, "JRZQ1D09": &dto.JRZQ1D09Req{}, "IVYZ2A8B": &dto.IVYZ2A8BReq{}, "IVYZ7C9D": &dto.IVYZ7C9DReq{}, "IVYZ5E3F": &dto.IVYZ5E3FReq{}, "YYSY4F2E": &dto.YYSY4F2EReq{}, "YYSY8B1C": &dto.YYSY8B1CReq{}, "YYSY6D9A": &dto.YYSY6D9AReq{}, "YYSY3E7F": &dto.YYSY3E7FReq{}, "FLXG5A3B": &dto.FLXG5A3BReq{}, "FLXG9C1D": &dto.FLXG9C1DReq{}, "FLXG2E8F": &dto.FLXG2E8FReq{}, "JRZQ3C7B": &dto.JRZQ3C7BReq{}, "JRZQ8A2D": &dto.JRZQ8A2DReq{}, "JRZQ5E9F": &dto.JRZQ5E9FReq{}, "JRZQ4B6C": &dto.JRZQ4B6CReq{}, "JRZQ7F1A": &dto.JRZQ7F1AReq{}, "DWBG6A2C": &dto.DWBG6A2CReq{}, "DWBG8B4D": &dto.DWBG8B4DReq{}, "FLXG8B4D": &dto.FLXG8B4DReq{}, "IVYZ81NC": &dto.IVYZ81NCReq{}, "IVYZ7F3A": &dto.IVYZ7F3AReq{}, "IVYZ3A7F": &dto.IVYZ3A7FReq{}, "IVYZ9D2E": &dto.IVYZ9D2EReq{}, "DWBG7F3A": &dto.DWBG7F3AReq{}, "YYSY8F3A": &dto.YYSY8F3AReq{}, "QCXG9P1C": &dto.QCXG9P1CReq{}, "JRZQ9E2A": &dto.JRZQ9E2AReq{}, "YYSY9A1B": &dto.YYSY9A1BReq{}, "YYSY8C2D": &dto.YYSY8C2DReq{}, "YYSY7D3E": &dto.YYSY7D3EReq{}, "JRZQ6F2A": &dto.JRZQ6F2AReq{}, "JRZQ8B3C": &dto.JRZQ8B3CReq{}, "JRZQ9D4E": &dto.JRZQ9D4EReq{}, "FLXG7E8F": &dto.FLXG7E8FReq{}, "QYGL5F6A": &dto.QYGL5F6AReq{}, "IVYZ6G7H": &dto.IVYZ6G7HReq{}, "IVYZ8I9J": &dto.IVYZ8I9JReq{}, } // 优先返回已配置的DTO if dto, exists := dtoMap[apiCode]; exists { return dto } // 检查是否为通用组合包(COMB开头且未单独配置) if len(apiCode) >= 4 && apiCode[:4] == "COMB" { // 对于通用组合包,返回一个通用的空结构体,表示无需特定参数验证 // 因为组合包的参数验证由各个子处理器负责 return &struct{}{} } return nil } // parseDTOFields 通过反射解析DTO结构体字段 func (s *FormConfigServiceImpl) parseDTOFields(dtoStruct interface{}) []FormField { var fields []FormField t := reflect.TypeOf(dtoStruct).Elem() for i := 0; i < t.NumField(); i++ { field := t.Field(i) // 获取JSON标签 jsonTag := field.Tag.Get("json") if jsonTag == "" { continue } // 获取验证标签 validateTag := field.Tag.Get("validate") // 解析验证规则 required := strings.Contains(validateTag, "required") validation := s.parseValidationRules(validateTag) // 根据字段类型和验证规则生成前端字段类型 fieldType := s.getFieldType(field.Type, validation) // 生成字段标签(将下划线转换为中文) label := s.generateFieldLabel(jsonTag) // 生成示例值 example := s.generateExampleValue(field.Type, jsonTag) // 生成占位符 placeholder := s.generatePlaceholder(jsonTag, fieldType) // 生成字段描述 description := s.generateDescription(jsonTag, validation) formField := FormField{ Name: jsonTag, Label: label, Type: fieldType, Required: required, Validation: validation, Description: description, Example: example, Placeholder: placeholder, } fields = append(fields, formField) } return fields } // parseValidationRules 解析验证规则 func (s *FormConfigServiceImpl) parseValidationRules(validateTag string) string { if validateTag == "" { return "" } // 将验证规则转换为前端可理解的格式 rules := strings.Split(validateTag, ",") var frontendRules []string for _, rule := range rules { rule = strings.TrimSpace(rule) switch { case rule == "required": frontendRules = append(frontendRules, "必填") case strings.HasPrefix(rule, "min="): min := strings.TrimPrefix(rule, "min=") frontendRules = append(frontendRules, "最小长度"+min) case strings.HasPrefix(rule, "max="): max := strings.TrimPrefix(rule, "max=") frontendRules = append(frontendRules, "最大长度"+max) case rule == "validMobileNo": frontendRules = append(frontendRules, "手机号格式") case rule == "validIDCard": frontendRules = append(frontendRules, "身份证格式") case rule == "validName": frontendRules = append(frontendRules, "姓名格式") case rule == "validUSCI": frontendRules = append(frontendRules, "统一社会信用代码格式") case rule == "validBankCard": frontendRules = append(frontendRules, "银行卡号格式") case rule == "validDate": frontendRules = append(frontendRules, "日期格式") case rule == "validAuthDate": frontendRules = append(frontendRules, "授权日期格式") case rule == "validTimeRange": frontendRules = append(frontendRules, "时间范围格式") case rule == "validMobileType": frontendRules = append(frontendRules, "手机类型") case rule == "validUniqueID": frontendRules = append(frontendRules, "唯一标识格式") case rule == "validReturnURL": frontendRules = append(frontendRules, "返回链接格式") case rule == "validAuthorizationURL": frontendRules = append(frontendRules, "授权链接格式") case strings.HasPrefix(rule, "oneof="): values := strings.TrimPrefix(rule, "oneof=") frontendRules = append(frontendRules, "可选值: "+values) } } return strings.Join(frontendRules, "、") } // getFieldType 根据字段类型和验证规则确定前端字段类型 func (s *FormConfigServiceImpl) getFieldType(fieldType reflect.Type, validation string) string { switch fieldType.Kind() { case reflect.String: if strings.Contains(validation, "手机号") { return "tel" } else if strings.Contains(validation, "身份证") { return "text" } else if strings.Contains(validation, "姓名") { return "text" } else if strings.Contains(validation, "日期") { return "date" } else if strings.Contains(validation, "链接") { return "url" } else if strings.Contains(validation, "可选值") { return "select" } return "text" case reflect.Int64: return "number" case reflect.Bool: return "checkbox" default: return "text" } } // generateFieldLabel 生成字段标签 func (s *FormConfigServiceImpl) generateFieldLabel(jsonTag string) string { // 将下划线命名转换为中文标签 labelMap := map[string]string{ "mobile_no": "手机号码", "id_card": "身份证号", "name": "姓名", "man_name": "男方姓名", "woman_name": "女方姓名", "man_id_card": "男方身份证", "woman_id_card": "女方身份证", "ent_name": "企业名称", "legal_person": "法人姓名", "ent_code": "企业代码", "auth_date": "授权日期", "time_range": "时间范围", "authorized": "是否授权", "authorization_url": "授权链接", "unique_id": "唯一标识", "return_url": "返回链接", "mobile_type": "手机类型", "start_date": "开始日期", "years": "年数", "bank_card": "银行卡号", } if label, exists := labelMap[jsonTag]; exists { return label } // 如果没有预定义,尝试自动转换 return strings.ReplaceAll(jsonTag, "_", " ") } // generateExampleValue 生成示例值 func (s *FormConfigServiceImpl) generateExampleValue(fieldType reflect.Type, jsonTag string) string { exampleMap := map[string]string{ "mobile_no": "13800138000", "id_card": "110101199001011234", "name": "张三", "man_name": "张三", "woman_name": "李四", "ent_name": "示例企业有限公司", "legal_person": "王五", "ent_code": "91110000123456789X", "auth_date": "2024-01-01", "time_range": "2024-01-01至2024-12-31", "authorized": "1", "years": "5", "bank_card": "6222021234567890123", "mobile_type": "移动", "start_date": "2024-01-01", "unique_id": "UNIQUE123456", "return_url": "https://example.com/return", "authorization_url": "https://example.com/auth", } if example, exists := exampleMap[jsonTag]; exists { return example } // 根据字段类型生成默认示例 switch fieldType.Kind() { case reflect.String: return "示例值" case reflect.Int64: return "123" case reflect.Bool: return "true" default: return "示例值" } } // generatePlaceholder 生成占位符 func (s *FormConfigServiceImpl) generatePlaceholder(jsonTag string, fieldType string) string { placeholderMap := map[string]string{ "mobile_no": "请输入11位手机号码", "id_card": "请输入18位身份证号码", "name": "请输入真实姓名", "man_name": "请输入男方真实姓名", "woman_name": "请输入女方真实姓名", "ent_name": "请输入企业全称", "legal_person": "请输入法人真实姓名", "ent_code": "请输入统一社会信用代码", "auth_date": "请选择授权日期", "time_range": "请输入查询时间范围", "authorized": "请选择是否授权", "years": "请输入查询年数(0-100)", "bank_card": "请输入银行卡号", "mobile_type": "请选择手机类型", "start_date": "请选择开始日期", "unique_id": "请输入唯一标识", "return_url": "请输入返回链接", "authorization_url": "请输入授权链接", } if placeholder, exists := placeholderMap[jsonTag]; exists { return placeholder } // 根据字段类型生成默认占位符 switch fieldType { case "tel": return "请输入电话号码" case "date": return "请选择日期" case "url": return "请输入链接地址" case "number": return "请输入数字" default: return "请输入" + s.generateFieldLabel(jsonTag) } } // generateDescription 生成字段描述 func (s *FormConfigServiceImpl) generateDescription(jsonTag string, validation string) string { descMap := map[string]string{ "mobile_no": "请输入11位手机号码", "id_card": "请输入18位身份证号码", "name": "请输入真实姓名", "man_name": "请输入男方真实姓名", "woman_name": "请输入女方真实姓名", "ent_name": "请输入企业全称", "legal_person": "请输入法人真实姓名", "ent_code": "请输入统一社会信用代码", "auth_date": "请输入授权日期,格式:YYYY-MM-DD", "time_range": "请输入查询时间范围", "authorized": "请输入是否授权:0-未授权,1-已授权", "years": "请输入查询年数(0-100)", "bank_card": "请输入银行卡号", "mobile_type": "请选择手机类型", "start_date": "请选择开始日期", "unique_id": "请输入唯一标识", "return_url": "请输入返回链接", "authorization_url": "请输入授权链接", } if desc, exists := descMap[jsonTag]; exists { return desc } return "请输入" + s.generateFieldLabel(jsonTag) }