diff --git a/app/user/cmd/api/desc/query/query.api b/app/user/cmd/api/desc/query/query.api index e3f38f4..d6e4943 100644 --- a/app/user/cmd/api/desc/query/query.api +++ b/app/user/cmd/api/desc/query/query.api @@ -32,12 +32,15 @@ type Query { UserId int64 `json:"user_id"` // 用户ID ProductName string `json:"product_name"` // 产品ID QueryParams map[string]interface{} `json:"query_params"` - QueryData []map[string]interface{} `json:"query_data"` + QueryData []QueryItem `json:"query_data"` CreateTime string `json:"create_time"` // 创建时间 UpdateTime string `json:"update_time"` // 更新时间 QueryState string `json:"query_state"` // 查询状态 } - +type QueryItem { + Feature interface{} `json:"feature"` + Data interface{} `json:"data"` // 这里可以是 map 或 具体的 struct +} // 获取查询临时订单 type ( QueryProvisionalOrderReq { diff --git a/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go b/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go index 176a172..2a62916 100644 --- a/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go +++ b/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go @@ -154,7 +154,7 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB } // ProcessQueryData 解密和反序列化 QueryData -func ProcessQueryData(queryData sql.NullString, target *[]map[string]interface{}, key []byte) error { +func ProcessQueryData(queryData sql.NullString, target *[]types.QueryItem, key []byte) error { queryDataStr := lzUtils.NullStringToString(queryData) if queryDataStr == "" { return nil diff --git a/app/user/cmd/api/internal/logic/query/queryexamplelogic.go b/app/user/cmd/api/internal/logic/query/queryexamplelogic.go index fe6a3bf..5eea0e1 100644 --- a/app/user/cmd/api/internal/logic/query/queryexamplelogic.go +++ b/app/user/cmd/api/internal/logic/query/queryexamplelogic.go @@ -6,8 +6,9 @@ import ( "tyc-server/app/user/cmd/api/internal/svc" "tyc-server/app/user/cmd/api/internal/types" "tyc-server/common/xerr" + "tyc-server/pkg/lzkit/crypto" - "github.com/jinzhu/copier" + "github.com/bytedance/sonic" "github.com/pkg/errors" "github.com/zeromicro/go-zero/core/logx" @@ -28,38 +29,86 @@ func NewQueryExampleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Quer } func (l *QueryExampleLogic) QueryExample(req *types.QueryExampleReq) (resp *types.QueryExampleResp, err error) { + // 根据产品特性标识获取产品信息 product, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, req.Feature) if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "示例报告, 获取商品信息失败: %v", err) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取商品信息失败, %v", err) } - exampleModel, err := l.svcCtx.ExampleModel.FindOneByProductId(l.ctx, product.Id) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "示例报告, 获取示例报告失败: %v", err) - } - var query types.Query - query.CreateTime = exampleModel.CreateTime.Format("2006-01-02 15:04:05") - query.UpdateTime = exampleModel.UpdateTime.Format("2006-01-02 15:04:05") - // 解密查询数据 - secretKey := l.svcCtx.Config.Encrypt.SecretKey - key, decodeErr := hex.DecodeString(secretKey) - if decodeErr != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取AES解密解药失败, %+v", err) + // 创建一个空的Query结构体来存储结果 + query := types.Query{ + ProductName: product.ProductName, + QueryData: make([]types.QueryItem, 0), + QueryParams: make(map[string]interface{}), } - processParamsErr := ProcessQueryParams(exampleModel.QueryParams, &query.QueryParams, key) - if processParamsErr != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告参数处理失败: %v", processParamsErr) - } - processErr := ProcessQueryData(exampleModel.QueryData, &query.QueryData, key) - if processErr != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结果处理失败: %v", processErr) - } - // 复制报告数据 - err = copier.Copy(&query, exampleModel) + exampleParams, err := l.svcCtx.ExampleParamsModel.FindOneByProductId(l.ctx, product.Id) if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 报告结构体复制失败, %+v", err) + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取示例参数失败, %v", err) } - query.ProductName = product.ProductName + // 将字符串类型的QueryParams解析为map[string]interface{} + var queryParams map[string]interface{} + if err := sonic.Unmarshal([]byte(exampleParams.QueryParams), &queryParams); err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 解析示例参数失败, %v", err) + } + query.QueryParams = queryParams + // 查询ProductFeatureModel获取产品相关的功能列表 + builder := l.svcCtx.ProductFeatureModel.SelectBuilder().Where("product_id = ?", product.Id) + productFeatures, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, builder, "") + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 查询 ProductFeatureModel 错误: %v", err) + } + // 从每个启用的特性获取示例数据并合并 + for _, pf := range productFeatures { + if pf.Enable != 1 { + continue // 跳过未启用的特性 + } + + // 根据特性ID查找示例数据 + example, err := l.svcCtx.ExampleModel.FindOneByFeatureId(l.ctx, pf.FeatureId) + if err != nil { + logx.Infof("示例报告, 特性ID %d 无示例数据: %v", pf.FeatureId, err) + continue // 如果没有示例数据就跳过 + } + + // 获取对应的Feature信息 + feature, err := l.svcCtx.FeatureModel.FindOne(l.ctx, pf.FeatureId) + if err != nil { + logx.Infof("示例报告, 无法获取特性ID %d 的信息: %v", pf.FeatureId, err) + continue + } + + var queryItem types.QueryItem + + // 解密查询数据 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取AES解密解药失败, %v", err) + } + // 解析示例内容 + if example.Content == "000" { + queryItem.Data = example.Content + } else { + // 解密数据 + decryptedData, decryptErr := crypto.AesDecrypt(example.Content, key) + if decryptErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 解密数据失败: %v", decryptErr) + } + err = sonic.Unmarshal([]byte(decryptedData), &queryItem.Data) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 解析示例内容失败: %v", err) + } + } + + // 添加特性信息 + queryItem.Feature = map[string]interface{}{ + "featureName": feature.Name, + "sort": pf.Sort, + } + // 添加到查询数据中 + query.QueryData = append(query.QueryData, queryItem) + } + return &types.QueryExampleResp{ Query: query, }, nil diff --git a/app/user/cmd/api/internal/service/apirequestService.go b/app/user/cmd/api/internal/service/apirequestService.go index 7b87a19..919bff4 100644 --- a/app/user/cmd/api/internal/service/apirequestService.go +++ b/app/user/cmd/api/internal/service/apirequestService.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "net/url" + "sort" "strings" "sync" "sync/atomic" @@ -49,7 +50,6 @@ type APIResponseData struct { Data json.RawMessage `json:"data"` // 这里用 RawMessage 来存储原始的 data TaskID string `json:"task_id,omitempty"` IsAsync bool `json:"is_async,omitempty"` - Sort int64 `json:"sort"` Success bool `json:"success"` Timestamp string `json:"timestamp"` Error string `json:"error,omitempty"` @@ -71,11 +71,9 @@ func (a *ApiRequestService) ProcessRequests(ctx context.Context, params []byte, } var featureIDs []int64 isImportantMap := make(map[int64]int64, len(productFeatureList)) - sortMap := make(map[int64]int64, len(productFeatureList)) for _, pf := range productFeatureList { featureIDs = append(featureIDs, pf.FeatureId) isImportantMap[pf.FeatureId] = pf.IsImportant - sortMap[pf.FeatureId] = pf.Sort } if len(featureIDs) == 0 { return nil, errors.New("featureIDs 是空的") @@ -113,7 +111,6 @@ func (a *ApiRequestService) ProcessRequests(ctx context.Context, params []byte, result := APIResponseData{ ApiID: feature.ApiId, Success: false, - Sort: sortMap[feature.Id], } timestamp := time.Now().Format("2006-01-02 15:04:05") var ( @@ -236,6 +233,16 @@ var requestProcessors = map[string]func(*ApiRequestService, context.Context, []b "mobilelocal": (*ApiRequestService).ProcessMobilelocalRequest, // 手机归属地 "sfz": (*ApiRequestService).ProcessSfzRequest, // 身份证归属地 "IDV044": (*ApiRequestService).ProcessIDV044Request, + + // New Feature + "PersonEnterprisePro": (*ApiRequestService).ProcessPersonEnterpriseProRequest, + "BehaviorRiskScan": (*ApiRequestService).ProcessBehaviorRiskScanRequest, + "G30BJ05": (*ApiRequestService).ProcessG30BJ05Request, + "G31BJ05": (*ApiRequestService).ProcessG31BJ05Request, + "G32BJ05": (*ApiRequestService).ProcessG32BJ05Request, + "G09XM02": (*ApiRequestService).ProcessG09XM02Request, + "G10XM02": (*ApiRequestService).ProcessG10XM02Request, + "G11BJ06": (*ApiRequestService).ProcessG11BJ06Request, } // PreprocessRequestApi 调用指定的请求处理函数 @@ -1392,16 +1399,71 @@ func (a *ApiRequestService) ProcessQ03SC01Request(ctx context.Context, params [] return nil, fmt.Errorf("外层 data 字段不存在") } + // 保留原有的递归解析和序列化逻辑 parseResult, err := lzUtils.RecursiveParse(dataResult.Raw) if err != nil { return nil, fmt.Errorf("递归反序列化") } + logx.Infof("parseResult: %v", parseResult) marshal, err := sonic.Marshal(parseResult) if err != nil { return nil, fmt.Errorf("序列化失败: %v", err) } + // 第二步:使用gjson预处理数据 + dataMap := make(map[string]interface{}) + + // 处理entout数据 + entoutArray := gjson.GetBytes(marshal, "entout").Array() + if len(entoutArray) > 0 { + // 检查是否存在count字段来判断是否有数据 + countField := entoutArray[0].Get("data.count") + if countField.Exists() { + // 有count字段,表示有数据 + entoutData := entoutArray[0].Get("data") + if entoutData.Exists() { + dataMap["data"] = json.RawMessage(entoutData.Raw) + } + } else { + // 没有count字段,使用空对象 + dataMap["data"] = json.RawMessage("{}") + } + } else { + dataMap["data"] = json.RawMessage("{}") + } + + // 处理sxbzxr数据(失信被执行人) + sxbzxrArray := dataResult.Get("sxbzxr").Array() + if len(sxbzxrArray) > 0 { + sxbzxrList := sxbzxrArray[0].Get("sxbzxr") + if sxbzxrList.Exists() && len(sxbzxrList.Array()) > 0 { + dataMap["sxbzxr"] = json.RawMessage(sxbzxrList.Raw) + } else { + dataMap["sxbzxr"] = json.RawMessage("[]") + } + } else { + dataMap["sxbzxr"] = json.RawMessage("[]") + } + + // 处理xgbzxr数据(限高被执行人) + xgbzxrArray := dataResult.Get("xgbzxr").Array() + if len(xgbzxrArray) > 0 { + xgbzxrList := xgbzxrArray[0].Get("xgbzxr") + if xgbzxrList.Exists() && len(xgbzxrList.Array()) > 0 { + dataMap["xgbzxr"] = json.RawMessage(xgbzxrList.Raw) + } else { + dataMap["xgbzxr"] = json.RawMessage("[]") + } + } else { + dataMap["xgbzxr"] = json.RawMessage("[]") + } + + result, err := sonic.Marshal(dataMap) + if err != nil { + return nil, fmt.Errorf("序列化预处理数据失败: %v", err) + } + return &APIInternalResult{ - Data: marshal, + Data: result, }, nil } @@ -1715,3 +1777,744 @@ func (a *ApiRequestService) ProcessIDV044Request(ctx context.Context, params []b Data: resp, }, nil } + +// PersonEnterprisePro 人企业关系加强版 +func (a *ApiRequestService) ProcessPersonEnterpriseProRequest(ctx context.Context, params []byte) (*APIInternalResult, error) { + idCard := gjson.GetBytes(params, "id_card") + // 设置最大调用次数上限 + maxApiCalls := 20 // 允许最多查询20个企业 + + if !idCard.Exists() { + return nil, errors.New("api请求, PersonEnterprisePro, 获取相关参数失败") + } + + request := map[string]interface{}{ + "pid": crypto.Md5Encrypt(idCard.String()), + } + resp, callApiErr := a.westDexService.G05HZ01CallAPI("G05HZ01", request) + if callApiErr != nil { + return nil, callApiErr + } + + // 处理股东人企关系的响应数据 + code := gjson.GetBytes(resp, "code") + if !code.Exists() { + return nil, fmt.Errorf("响应中缺少 code 字段") + } + + // 判断 code 是否等于 "0000" + if code.String() == "0000" { + // 获取 data 字段的值 + data := gjson.GetBytes(resp, "data") + if !data.Exists() { + return nil, fmt.Errorf("响应中缺少 data 字段") + } + + // 使用gjson获取企业列表 + datalistResult := gjson.Get(data.Raw, "datalist") + if !datalistResult.Exists() { + return nil, fmt.Errorf("datalist字段不存在") + } + + // 获取所有企业并进行排序 + companies := datalistResult.Array() + + // 创建企业对象切片,用于排序 + type CompanyWithPriority struct { + Index int + Data gjson.Result + RelationshipVal int // 关系权重值 + RelationCount int // 关系数量 + AdminPenalty int // 行政处罚数量 + Executed int // 被执行人数量 + Dishonest int // 失信被执行人数量 + } + + companiesWithPriority := make([]CompanyWithPriority, 0, len(companies)) + + // 遍历企业,计算优先级 + for i, companyJson := range companies { + // 统计行政处罚、被执行人、失信被执行人 + adminPenalty := 0 + executed := 0 + dishonest := 0 + + // 检查行政处罚字段是否存在并获取数组长度 + adminPenaltyResult := companyJson.Get("adminPenalty") + if adminPenaltyResult.Exists() && adminPenaltyResult.IsArray() { + adminPenalty = len(adminPenaltyResult.Array()) + } + + // 检查被执行人字段是否存在并获取数组长度 + executedPersonResult := companyJson.Get("executedPerson") + if executedPersonResult.Exists() && executedPersonResult.IsArray() { + executed = len(executedPersonResult.Array()) + } + + // 检查失信被执行人字段是否存在并获取数组长度 + dishonestExecutedPersonResult := companyJson.Get("dishonestExecutedPerson") + if dishonestExecutedPersonResult.Exists() && dishonestExecutedPersonResult.IsArray() { + dishonest = len(dishonestExecutedPersonResult.Array()) + } + + // 计算relationship权重 + relationshipVal := 0 + relationCount := 0 + + // 获取relationship数组 + relationshipResult := companyJson.Get("relationship") + if relationshipResult.Exists() && relationshipResult.IsArray() { + relationships := relationshipResult.Array() + // 统计各类关系的数量和权重 + for _, rel := range relationships { + relationCount++ + relStr := rel.String() + + // 根据关系类型设置权重,权重顺序: + // 股东(6) > 历史股东(5) > 法人(4) > 历史法人(3) > 高管(2) > 历史高管(1) + switch relStr { + case "sh": // 股东 + if relationshipVal < 6 { + relationshipVal = 6 + } + case "his_sh": // 历史股东 + if relationshipVal < 5 { + relationshipVal = 5 + } + case "lp": // 法人 + if relationshipVal < 4 { + relationshipVal = 4 + } + case "his_lp": // 历史法人 + if relationshipVal < 3 { + relationshipVal = 3 + } + case "tm": // 高管 + if relationshipVal < 2 { + relationshipVal = 2 + } + case "his_tm": // 历史高管 + if relationshipVal < 1 { + relationshipVal = 1 + } + } + } + } + + companiesWithPriority = append(companiesWithPriority, CompanyWithPriority{ + Index: i, + Data: companyJson, + RelationshipVal: relationshipVal, + RelationCount: relationCount, + AdminPenalty: adminPenalty, + Executed: executed, + Dishonest: dishonest, + }) + } + + // 按优先级排序 + sort.Slice(companiesWithPriority, func(i, j int) bool { + // 首先根据是否有失信被执行人排序 + if companiesWithPriority[i].Dishonest != companiesWithPriority[j].Dishonest { + return companiesWithPriority[i].Dishonest > companiesWithPriority[j].Dishonest + } + + // 然后根据是否有被执行人排序 + if companiesWithPriority[i].Executed != companiesWithPriority[j].Executed { + return companiesWithPriority[i].Executed > companiesWithPriority[j].Executed + } + + // 然后根据是否有行政处罚排序 + if companiesWithPriority[i].AdminPenalty != companiesWithPriority[j].AdminPenalty { + return companiesWithPriority[i].AdminPenalty > companiesWithPriority[j].AdminPenalty + } + + // 然后按relationship类型排序 + if companiesWithPriority[i].RelationshipVal != companiesWithPriority[j].RelationshipVal { + return companiesWithPriority[i].RelationshipVal > companiesWithPriority[j].RelationshipVal + } + + // 最后按relationship数量排序 + return companiesWithPriority[i].RelationCount > companiesWithPriority[j].RelationCount + }) + + // 限制处理的企业数量 + processCount := len(companiesWithPriority) + if processCount > maxApiCalls { + processCount = maxApiCalls + } + + // 只处理前N个优先级高的企业 + prioritizedCompanies := companiesWithPriority[:processCount] + + // 使用WaitGroup和chan处理并发 + var wg sync.WaitGroup + results := make(chan struct { + index int + data []byte + err error + }, processCount) + + // 对按优先级排序的前N个企业进行涉诉信息查询 + for _, company := range prioritizedCompanies { + wg.Add(1) + go func(origIndex int, companyInfo gjson.Result) { + defer wg.Done() + logx.Infof("开始处理企业[%d],企业名称: %s,统一社会信用代码: %s", origIndex, companyInfo.Get("basicInfo.name").String(), companyInfo.Get("basicInfo.creditCode").String()) + // 提取企业名称和统一社会信用代码 + orgName := companyInfo.Get("basicInfo.name") + creditCode := companyInfo.Get("basicInfo.creditCode") + + if !orgName.Exists() || !creditCode.Exists() { + results <- struct { + index int + data []byte + err error + }{origIndex, nil, fmt.Errorf("企业名称或统一社会信用代码不存在")} + return + } + + // 解析原始公司信息为map + var companyMap map[string]interface{} + if err := json.Unmarshal([]byte(companyInfo.Raw), &companyMap); err != nil { + results <- struct { + index int + data []byte + err error + }{origIndex, nil, fmt.Errorf("解析企业信息失败: %v", err)} + return + } + + // 构造调用Q03SC01的参数 + q03Params, err := json.Marshal(map[string]string{ + "ent_name": orgName.String(), + "ent_code": creditCode.String(), + }) + if err != nil { + // 参数构造失败,但不影响整体处理 + logx.Errorf("构造企业[%s]涉诉查询参数失败: %v", orgName.String(), err) + companyMap["lawsuitInfo"] = map[string]interface{}{} + } else { + // 调用Q03SC01接口获取企业涉诉信息 + lawsuitData, err := a.ProcessQ03SC01Request(ctx, q03Params) + // 无论是否有错误,都继续处理 + if err != nil { + // 可能是正常没有涉诉数据,设置为空对象 + logx.Infof("企业[%s]涉诉信息查询结果: %v", orgName.String(), err) + companyMap["lawsuitInfo"] = map[string]interface{}{} + } else if len(lawsuitData.Data) == 0 || string(lawsuitData.Data) == "{}" || string(lawsuitData.Data) == "null" { + // 无涉诉数据 + companyMap["lawsuitInfo"] = map[string]interface{}{} + } else { + // 解析涉诉信息 + var lawsuitInfo interface{} + if err := json.Unmarshal(lawsuitData.Data, &lawsuitInfo); err != nil { + logx.Errorf("解析企业[%s]涉诉信息失败: %v", orgName.String(), err) + companyMap["lawsuitInfo"] = map[string]interface{}{} + } else { + // 添加涉诉信息到企业信息中 + companyMap["lawsuitInfo"] = lawsuitInfo + } + } + } + + // 序列化更新后的企业信息 + companyData, err := json.Marshal(companyMap) + if err != nil { + results <- struct { + index int + data []byte + err error + }{origIndex, nil, fmt.Errorf("序列化企业信息失败: %v", err)} + return + } + + results <- struct { + index int + data []byte + err error + }{origIndex, companyData, nil} + }(company.Index, company.Data) + } + + // 关闭结果通道 + go func() { + wg.Wait() + close(results) + }() + + // 解析原始数据为map + var dataMap map[string]interface{} + if err := json.Unmarshal([]byte(data.Raw), &dataMap); err != nil { + return nil, fmt.Errorf("解析data字段失败: %v", err) + } + + // 获取原始企业列表 + originalDatalist, ok := dataMap["datalist"].([]interface{}) + if !ok { + return nil, fmt.Errorf("无法获取原始企业列表") + } + + // 创建结果映射,用于保存已处理的企业 + processedCompanies := make(map[int]interface{}) + + // 收集处理过的企业数据 + for result := range results { + if result.err != nil { + logx.Errorf("处理企业失败: %v", result.err) + continue + } + + if result.data != nil { + var companyMap interface{} + if err := json.Unmarshal(result.data, &companyMap); err == nil { + processedCompanies[result.index] = companyMap + } + } + } + + // 更新企业列表 + // 处理过的用新数据,未处理的保留原样 + updatedDatalist := make([]interface{}, len(originalDatalist)) + for i, company := range originalDatalist { + if processed, exists := processedCompanies[i]; exists { + // 已处理的企业,使用新数据 + updatedDatalist[i] = processed + } else { + // 未处理的企业,保留原始数据并添加空的涉诉信息 + companyMap, ok := company.(map[string]interface{}) + if ok { + // 为未处理的企业添加空的涉诉信息 + companyMap["lawsuitInfo"] = map[string]interface{}{} + updatedDatalist[i] = companyMap + } else { + updatedDatalist[i] = company + } + } + } + + // 更新原始数据中的企业列表 + dataMap["datalist"] = updatedDatalist + + // 序列化最终结果 + result, err := json.Marshal(dataMap) + if err != nil { + return nil, fmt.Errorf("序列化最终结果失败: %v", err) + } + + return &APIInternalResult{ + Data: result, + }, nil + } + + // code不等于"0000",返回错误 + return nil, fmt.Errorf("响应code错误: %s", code.String()) +} + +func (a *ApiRequestService) ProcessBehaviorRiskScanRequest(ctx context.Context, params []byte) (*APIInternalResult, error) { + name := gjson.GetBytes(params, "name") + idCard := gjson.GetBytes(params, "id_card") + mobile := gjson.GetBytes(params, "mobile") + + if !name.Exists() || !idCard.Exists() || !mobile.Exists() { + return nil, errors.New("api请求, BehaviorRiskScan, 获取相关参数失败") + } + + var wg sync.WaitGroup + type apiResult struct { + name string + data []byte + err error + } + results := make(chan apiResult, 5) // 5个风险检测项 + + // 并行调用五个不同的风险检测API + wg.Add(4) + + // 黑灰产检测 + go func() { + defer wg.Done() + data, err := a.ProcessG30BJ05Request(ctx, params) + results <- apiResult{name: "black_gray_level", data: data.Data, err: err} + }() + + // 电诈风险预警 + go func() { + defer wg.Done() + data, err := a.ProcessG31BJ05Request(ctx, params) + results <- apiResult{name: "telefraud_level", data: data.Data, err: err} + }() + + // 团伙欺诈排查 + go func() { + defer wg.Done() + data, err := a.ProcessG32BJ05Request(ctx, params) + results <- apiResult{name: "fraud_group", data: data.Data, err: err} + }() + + // // 反诈反赌核验 + go func() { + defer wg.Done() + data, err := a.ProcessRIS031Request(ctx, params) + results <- apiResult{name: "anti_fraud_gaming", data: data.Data, err: err} + }() + + // 风险等级 + go func() { + defer wg.Done() + data, err := a.ProcessG34BJ03Request(ctx, params) + results <- apiResult{name: "risk_level", data: data.Data, err: err} + }() + + // 关闭结果通道 + go func() { + wg.Wait() + close(results) + }() + + // 收集所有结果 + resultMap := make(map[string]interface{}) + var errors []string + + for result := range results { + if result.err != nil { + // 记录错误但继续处理其他结果 + errors = append(errors, fmt.Sprintf("%s: %v", result.name, result.err)) + continue + } + + // 解析JSON结果并添加到结果映射 + var parsedData interface{} + if err := json.Unmarshal(result.data, &parsedData); err != nil { + errors = append(errors, fmt.Sprintf("解析%s数据失败: %v", result.name, err)) + } else { + resultMap[result.name] = parsedData + } + } + + // 添加错误信息到结果中(如果存在) + if len(errors) > 0 { + resultMap["errors"] = errors + } + + // 序列化最终结果 + finalResult, err := json.Marshal(resultMap) + if err != nil { + return nil, fmt.Errorf("序列化行为风险扫描结果失败: %v", err) + } + + return &APIInternalResult{ + Data: finalResult, + }, nil +} + +// G30BJ05 黑灰产 +func (a *ApiRequestService) ProcessG30BJ05Request(ctx context.Context, params []byte) (*APIInternalResult, error) { + name := gjson.GetBytes(params, "name") + idCard := gjson.GetBytes(params, "id_card") + Mobile := gjson.GetBytes(params, "mobile") + + if !name.Exists() || !idCard.Exists() || !Mobile.Exists() { + return nil, errors.New("api请求, G30BJ05, 获取相关参数失败") + } + + request := map[string]interface{}{ + "data": map[string]interface{}{ + "name": a.westDexService.Encrypt(name.String()), + "id": a.westDexService.Encrypt(idCard.String()), + "cell": a.westDexService.Encrypt(Mobile.String()), + }, + } + resp, callApiErr := a.westDexService.CallAPI("G30BJ05", request) + if callApiErr != nil { + return nil, callApiErr + } + fmt.Println(resp) + flagBlackgraylevel := gjson.GetBytes(resp, "flag_blackgraylevel") + if !flagBlackgraylevel.Exists() || flagBlackgraylevel.String() != "1" { + return nil, fmt.Errorf("自然人黑灰产信息查询失败") + } + + bglLevel := gjson.GetBytes(resp, "bgl_level") + if !bglLevel.Exists() { + return nil, fmt.Errorf("bgl_level 字段不存在") + } + + return &APIInternalResult{ + Data: []byte(bglLevel.Raw), + }, nil +} + +// G31BJ05 电诈风险预警 +func (a *ApiRequestService) ProcessG31BJ05Request(ctx context.Context, params []byte) (*APIInternalResult, error) { + name := gjson.GetBytes(params, "name") + idCard := gjson.GetBytes(params, "id_card") + Mobile := gjson.GetBytes(params, "mobile") + + if !name.Exists() || !idCard.Exists() || !Mobile.Exists() { + return nil, errors.New("api请求, G31BJ05, 获取相关参数失败") + } + + request := map[string]interface{}{ + "data": map[string]interface{}{ + "name": a.westDexService.Encrypt(name.String()), + "id": a.westDexService.Encrypt(idCard.String()), + "cell": a.westDexService.Encrypt(Mobile.String()), + }, + } + resp, callApiErr := a.westDexService.CallAPI("G31BJ05", request) + if callApiErr != nil { + return nil, callApiErr + } + fmt.Println(resp) + flagTelefraudpredictstd := gjson.GetBytes(resp, "flag_telefraudpredictstd") + if !flagTelefraudpredictstd.Exists() || flagTelefraudpredictstd.String() != "1" { + return nil, fmt.Errorf("自然人电诈风险预警查询失败") + } + + tfpsLevel := gjson.GetBytes(resp, "tfps_level") + if !tfpsLevel.Exists() { + return nil, fmt.Errorf("tfps_level 字段不存在") + } + + return &APIInternalResult{ + Data: []byte(tfpsLevel.Raw), + }, nil +} + +// G32BJ05 团伙欺诈排查 +func (a *ApiRequestService) ProcessG32BJ05Request(ctx context.Context, params []byte) (*APIInternalResult, error) { + name := gjson.GetBytes(params, "name") + idCard := gjson.GetBytes(params, "id_card") + Mobile := gjson.GetBytes(params, "mobile") + + if !name.Exists() || !idCard.Exists() || !Mobile.Exists() { + return nil, errors.New("api请求, G32BJ05, 获取相关参数失败") + } + + request := map[string]interface{}{ + "data": map[string]interface{}{ + "name": a.westDexService.Encrypt(name.String()), + "id": a.westDexService.Encrypt(idCard.String()), + "cell": a.westDexService.Encrypt(Mobile.String()), + }, + } + resp, callApiErr := a.westDexService.CallAPI("G32BJ05", request) + if callApiErr != nil { + return nil, callApiErr + } + + flagFraudrelation := gjson.GetBytes(resp, "flag_fraudrelation") + if !flagFraudrelation.Exists() || flagFraudrelation.String() != "1" { + return nil, fmt.Errorf("自然人团伙欺诈排查查询失败") + } + frgListLevel := gjson.GetBytes(resp, "frg_list_level") + if !frgListLevel.Exists() { + return nil, fmt.Errorf("frg_list_level 字段不存在") + } + + frgGroupNum := gjson.GetBytes(resp, "frg_group_num") + if !frgGroupNum.Exists() { + return nil, fmt.Errorf("frg_group_num 字段不存在") + } + + // 构建包含两个字段的JSON响应 + result := map[string]interface{}{ + "frg_list_level": frgListLevel.Value(), + "frg_group_num": frgGroupNum.Value(), + } + + resultJSON, err := json.Marshal(result) + if err != nil { + return nil, fmt.Errorf("序列化结果失败: %v", err) + } + + return &APIInternalResult{ + Data: resultJSON, + }, nil +} +func (a *ApiRequestService) ProcessG09XM02Request(ctx context.Context, params []byte) (*APIInternalResult, error) { + idCard := gjson.GetBytes(params, "id_card") + name := gjson.GetBytes(params, "name") + if !idCard.Exists() || !name.Exists() { + return nil, errors.New("api请求, G09XM02, 获取相关参数失败") + } + request := map[string]interface{}{ + "data": map[string]interface{}{ + "idCard": a.westDexService.Encrypt(idCard.String()), + "name": a.westDexService.Encrypt(name.String()), + }, + } + resp, err := a.westDexService.CallAPI("G09XM02", request) + if err != nil && resp == nil { + return nil, fmt.Errorf("婚姻状态查询失败: %v", err) + } + result := gjson.GetBytes(resp, "data.data") + if !result.Exists() { + return nil, fmt.Errorf("婚姻状态查询失败") + } + + // 获取原始结果 + rawResult := result.String() + + // 根据结果转换状态码 + var statusCode string + switch { + case strings.HasPrefix(rawResult, "INR"): + statusCode = "0" // 匹配不成功 + case strings.HasPrefix(rawResult, "IA"): + statusCode = "1" // 结婚 + case strings.HasPrefix(rawResult, "IB"): + statusCode = "2" // 离婚 + default: + return nil, fmt.Errorf("婚姻状态查询失败,未知状态码: %s", statusCode) + } + + // 构建新的返回结果 + response := map[string]string{ + "status": statusCode, + } + + // 序列化为JSON + jsonResponse, err := json.Marshal(response) + if err != nil { + return nil, fmt.Errorf("序列化结果失败: %v", err) + } + + return &APIInternalResult{ + Data: jsonResponse, + }, nil +} + +func (a *ApiRequestService) ProcessG10XM02Request(ctx context.Context, params []byte) (*APIInternalResult, error) { + // 提取男方和女方信息 + nameMan := gjson.GetBytes(params, "nameMan") + idCardMan := gjson.GetBytes(params, "idCardMan") + nameWoman := gjson.GetBytes(params, "nameWoman") + idCardWoman := gjson.GetBytes(params, "idCardWoman") + + // 校验是否存在必要参数 + if !nameMan.Exists() || !idCardMan.Exists() || !nameWoman.Exists() || !idCardWoman.Exists() { + return nil, errors.New("请求参数缺失:需要提供男方和女方的姓名及身份证号") + } + + // 构造请求数据 + request := map[string]interface{}{ + "data": map[string]interface{}{ + "idCardMan": a.westDexService.Encrypt(idCardMan.String()), + "nameMan": a.westDexService.Encrypt(nameMan.String()), + "idCardWoman": a.westDexService.Encrypt(idCardWoman.String()), + "nameWoman": a.westDexService.Encrypt(nameWoman.String()), + }, + } + + // 调用 API + resp, callApiErr := a.westDexService.CallAPI("G10XM02", request) + if callApiErr != nil && resp == nil { + return nil, callApiErr + } + + result := gjson.GetBytes(resp, "data.data") + if !result.Exists() { + return nil, fmt.Errorf("婚姻状态查询失败") + } + + // 获取原始结果 + rawResult := result.String() + + // 根据结果转换状态码 + var statusCode string + switch { + case strings.HasPrefix(rawResult, "INR"): + statusCode = "0" // 匹配不成功 + case strings.HasPrefix(rawResult, "IA"): + statusCode = "1" // 结婚 + case strings.HasPrefix(rawResult, "IB"): + statusCode = "2" // 离婚 + default: + return nil, fmt.Errorf("婚姻状态查询失败,未知状态码: %s", statusCode) + } + + // 构建新的返回结果 + response := map[string]string{ + "status": statusCode, + } + + // 序列化为JSON + jsonResponse, err := json.Marshal(response) + if err != nil { + return nil, fmt.Errorf("序列化结果失败: %v", err) + } + + return &APIInternalResult{ + Data: jsonResponse, + }, nil +} +func (a *ApiRequestService) ProcessG11BJ06Request(ctx context.Context, params []byte) (*APIInternalResult, error) { + idCard := gjson.GetBytes(params, "id_card") + name := gjson.GetBytes(params, "name") + if !idCard.Exists() || !name.Exists() { + return nil, errors.New("api请求, G11BJ06, 获取相关参数失败") + } + request := map[string]interface{}{ + "data": map[string]interface{}{ + "id_card_value": a.westDexService.Encrypt(idCard.String()), + "name_value": a.westDexService.Encrypt(name.String()), + }, + } + resp, err := a.westDexService.CallAPI("G11BJ06", request) + if err != nil && resp == nil { + return nil, fmt.Errorf("教育经历核验查询失败: %v", err) + } + + // 解析响应 + codeResult := gjson.GetBytes(resp, "data.education_background.code") + if !codeResult.Exists() { + return nil, fmt.Errorf("教育经历核验查询失败: 返回数据缺少code字段") + } + + code := codeResult.String() + + var result map[string]interface{} + + switch code { + case "9100": + // 查询成功有结果 + eduResultArray := gjson.GetBytes(resp, "data.education_background.data").Array() + var processedEduData []interface{} + + // 提取每个元素中Raw字段的实际内容 + for _, item := range eduResultArray { + var eduInfo interface{} + if err := json.Unmarshal([]byte(item.Raw), &eduInfo); err != nil { + return nil, fmt.Errorf("解析教育信息失败: %v", err) + } + processedEduData = append(processedEduData, eduInfo) + } + + result = map[string]interface{}{ + "data": processedEduData, + "status": 1, + } + case "9000": + // 查询成功无结果 + result = map[string]interface{}{ + "data": []interface{}{}, + "status": 0, + } + default: + // 其他情况视为错误 + errMsg := gjson.GetBytes(resp, "data.education_background.msg").String() + return nil, fmt.Errorf("教育经历核验查询失败: %s (code: %s)", errMsg, code) + } + + // 将结果转为JSON字节 + jsonResult, err := json.Marshal(result) + if err != nil { + return nil, fmt.Errorf("处理教育经历查询结果失败: %v", err) + } + + return &APIInternalResult{ + Data: jsonResult, + }, nil +} diff --git a/app/user/cmd/api/internal/svc/servicecontext.go b/app/user/cmd/api/internal/svc/servicecontext.go index 89d8425..23fb258 100644 --- a/app/user/cmd/api/internal/svc/servicecontext.go +++ b/app/user/cmd/api/internal/svc/servicecontext.go @@ -27,6 +27,7 @@ type ServiceContext struct { QueryModel model.QueryModel GlobalNotificationsModel model.GlobalNotificationsModel ExampleModel model.ExampleModel + ExampleParamsModel model.ExampleParamsModel AlipayService *service.AliPayService WechatPayService *service.WechatPayService ApplePayService *service.ApplePayService @@ -83,6 +84,7 @@ func NewServiceContext(c config.Config) *ServiceContext { OrderModel: model.NewOrderModel(db, c.CacheRedis), QueryModel: model.NewQueryModel(db, c.CacheRedis), ExampleModel: model.NewExampleModel(db, c.CacheRedis), + ExampleParamsModel: model.NewExampleParamsModel(db, c.CacheRedis), GlobalNotificationsModel: model.NewGlobalNotificationsModel(db, c.CacheRedis), FeatureModel: featureModel, ProductFeatureModel: productFeatureModel, diff --git a/app/user/cmd/api/internal/types/types.go b/app/user/cmd/api/internal/types/types.go index f216e8d..0b2a818 100644 --- a/app/user/cmd/api/internal/types/types.go +++ b/app/user/cmd/api/internal/types/types.go @@ -90,15 +90,15 @@ type ProductResponse struct { } type Query struct { - Id int64 `json:"id"` // 主键ID - OrderId int64 `json:"order_id"` // 订单ID - UserId int64 `json:"user_id"` // 用户ID - ProductName string `json:"product_name"` // 产品ID - QueryParams map[string]interface{} `json:"query_params"` - QueryData []map[string]interface{} `json:"query_data"` - CreateTime string `json:"create_time"` // 创建时间 - UpdateTime string `json:"update_time"` // 更新时间 - QueryState string `json:"query_state"` // 查询状态 + Id int64 `json:"id"` // 主键ID + OrderId int64 `json:"order_id"` // 订单ID + UserId int64 `json:"user_id"` // 用户ID + ProductName string `json:"product_name"` // 产品ID + QueryParams map[string]interface{} `json:"query_params"` + QueryData []QueryItem `json:"query_data"` + CreateTime string `json:"create_time"` // 创建时间 + UpdateTime string `json:"update_time"` // 更新时间 + QueryState string `json:"query_state"` // 查询状态 } type QueryDetailByOrderIdReq struct { @@ -133,6 +133,11 @@ type QueryExampleResp struct { Query } +type QueryItem struct { + Feature interface{} `json:"feature"` + Data interface{} `json:"data"` // 这里可以是 map 或 具体的 struct +} + type QueryListReq struct { Page int64 `form:"page"` // 页码 PageSize int64 `form:"page_size"` // 每页数据量 diff --git a/app/user/model/exampleModel_gen.go b/app/user/model/exampleModel_gen.go index 1280572..9064d83 100644 --- a/app/user/model/exampleModel_gen.go +++ b/app/user/model/exampleModel_gen.go @@ -27,14 +27,16 @@ var ( exampleRowsWithPlaceHolder = strings.Join(stringx.Remove(exampleFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" cacheTycExampleIdPrefix = "cache:tyc:example:id:" - cacheTycExampleProductIdPrefix = "cache:tyc:example:productId:" + cacheTycExampleApiIdPrefix = "cache:tyc:example:apiId:" + cacheTycExampleFeatureIdPrefix = "cache:tyc:example:featureId:" ) type ( exampleModel interface { Insert(ctx context.Context, session sqlx.Session, data *Example) (sql.Result, error) FindOne(ctx context.Context, id int64) (*Example, error) - FindOneByProductId(ctx context.Context, productId int64) (*Example, error) + FindOneByApiId(ctx context.Context, apiId string) (*Example, error) + FindOneByFeatureId(ctx context.Context, featureId int64) (*Example, error) Update(ctx context.Context, session sqlx.Session, data *Example) (sql.Result, error) UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Example) error Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error @@ -56,15 +58,15 @@ type ( } Example struct { - Id int64 `db:"id"` // 主键ID - ProductId int64 `db:"product_id"` // 产品ID(直接关联到产品) - QueryParams string `db:"query_params"` // 查询params数据 - QueryData sql.NullString `db:"query_data"` // 查询结果数据 - DelState int64 `db:"del_state"` // 删除状态 - Version int64 `db:"version"` // 版本号 - CreateTime time.Time `db:"create_time"` // 创建时间 - UpdateTime time.Time `db:"update_time"` // 更新时间 - DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + Id int64 `db:"id"` // 主键ID + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + ApiId string `db:"api_id"` // API标识 + FeatureId int64 `db:"feature_id"` // 关联feature表的ID + Content string `db:"content"` // 内容 } ) @@ -77,15 +79,16 @@ func newExampleModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultExampleModel func (m *defaultExampleModel) Insert(ctx context.Context, session sqlx.Session, data *Example) (sql.Result, error) { data.DelState = globalkey.DelStateNo + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, data.Id) - tycExampleProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleProductIdPrefix, data.ProductId) return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, exampleRowsExpectAutoSet) if session != nil { - return session.ExecCtx(ctx, query, data.ProductId, data.QueryParams, data.QueryData, data.DelState, data.Version, data.DeleteTime) + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ApiId, data.FeatureId, data.Content) } - return conn.ExecCtx(ctx, query, data.ProductId, data.QueryParams, data.QueryData, data.DelState, data.Version, data.DeleteTime) - }, tycExampleIdKey, tycExampleProductIdKey) + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ApiId, data.FeatureId, data.Content) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) } func (m *defaultExampleModel) FindOne(ctx context.Context, id int64) (*Example, error) { @@ -105,12 +108,32 @@ func (m *defaultExampleModel) FindOne(ctx context.Context, id int64) (*Example, } } -func (m *defaultExampleModel) FindOneByProductId(ctx context.Context, productId int64) (*Example, error) { - tycExampleProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleProductIdPrefix, productId) +func (m *defaultExampleModel) FindOneByApiId(ctx context.Context, apiId string) (*Example, error) { + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, apiId) var resp Example - err := m.QueryRowIndexCtx(ctx, &resp, tycExampleProductIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { - query := fmt.Sprintf("select %s from %s where `product_id` = ? and del_state = ? limit 1", exampleRows, m.table) - if err := conn.QueryRowCtx(ctx, &resp, query, productId, globalkey.DelStateNo); err != nil { + err := m.QueryRowIndexCtx(ctx, &resp, tycExampleApiIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `api_id` = ? and del_state = ? limit 1", exampleRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, apiId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultExampleModel) FindOneByFeatureId(ctx context.Context, featureId int64) (*Example, error) { + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, featureId) + var resp Example + err := m.QueryRowIndexCtx(ctx, &resp, tycExampleFeatureIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `feature_id` = ? and del_state = ? limit 1", exampleRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, featureId, globalkey.DelStateNo); err != nil { return nil, err } return resp.Id, nil @@ -130,15 +153,16 @@ func (m *defaultExampleModel) Update(ctx context.Context, session sqlx.Session, if err != nil { return nil, err } + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, data.Id) - tycExampleProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleProductIdPrefix, data.ProductId) return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, exampleRowsWithPlaceHolder) if session != nil { - return session.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.QueryData, newData.DelState, newData.Version, newData.DeleteTime, newData.Id) + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id) } - return conn.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.QueryData, newData.DelState, newData.Version, newData.DeleteTime, newData.Id) - }, tycExampleIdKey, tycExampleProductIdKey) + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) } func (m *defaultExampleModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Example) error { @@ -153,15 +177,16 @@ func (m *defaultExampleModel) UpdateWithVersion(ctx context.Context, session sql if err != nil { return err } + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, data.Id) - tycExampleProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleProductIdPrefix, data.ProductId) sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, exampleRowsWithPlaceHolder) if session != nil { - return session.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.QueryData, newData.DelState, newData.Version, newData.DeleteTime, newData.Id, oldVersion) + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id, oldVersion) } - return conn.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.QueryData, newData.DelState, newData.Version, newData.DeleteTime, newData.Id, oldVersion) - }, tycExampleIdKey, tycExampleProductIdKey) + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id, oldVersion) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) if err != nil { return err } @@ -384,15 +409,16 @@ func (m *defaultExampleModel) Delete(ctx context.Context, session sqlx.Session, return err } + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, id) - tycExampleProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleProductIdPrefix, data.ProductId) _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { query := fmt.Sprintf("delete from %s where `id` = ?", m.table) if session != nil { return session.ExecCtx(ctx, query, id) } return conn.ExecCtx(ctx, query, id) - }, tycExampleIdKey, tycExampleProductIdKey) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) return err } func (m *defaultExampleModel) formatPrimary(primary interface{}) string { diff --git a/app/user/model/exampleParamsModel.go b/app/user/model/exampleParamsModel.go new file mode 100644 index 0000000..bd09ef1 --- /dev/null +++ b/app/user/model/exampleParamsModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ ExampleParamsModel = (*customExampleParamsModel)(nil) + +type ( + // ExampleParamsModel is an interface to be customized, add more methods here, + // and implement the added methods in customExampleParamsModel. + ExampleParamsModel interface { + exampleParamsModel + } + + customExampleParamsModel struct { + *defaultExampleParamsModel + } +) + +// NewExampleParamsModel returns a model for the database table. +func NewExampleParamsModel(conn sqlx.SqlConn, c cache.CacheConf) ExampleParamsModel { + return &customExampleParamsModel{ + defaultExampleParamsModel: newExampleParamsModel(conn, c), + } +} diff --git a/app/user/model/exampleParamsModel_gen.go b/app/user/model/exampleParamsModel_gen.go new file mode 100644 index 0000000..665e148 --- /dev/null +++ b/app/user/model/exampleParamsModel_gen.go @@ -0,0 +1,407 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "tyc-server/common/globalkey" +) + +var ( + exampleParamsFieldNames = builder.RawFieldNames(&ExampleParams{}) + exampleParamsRows = strings.Join(exampleParamsFieldNames, ",") + exampleParamsRowsExpectAutoSet = strings.Join(stringx.Remove(exampleParamsFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + exampleParamsRowsWithPlaceHolder = strings.Join(stringx.Remove(exampleParamsFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheTycExampleParamsIdPrefix = "cache:tyc:exampleParams:id:" + cacheTycExampleParamsProductIdPrefix = "cache:tyc:exampleParams:productId:" +) + +type ( + exampleParamsModel interface { + Insert(ctx context.Context, session sqlx.Session, data *ExampleParams) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*ExampleParams, error) + FindOneByProductId(ctx context.Context, productId int64) (*ExampleParams, error) + Update(ctx context.Context, session sqlx.Session, data *ExampleParams) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *ExampleParams) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *ExampleParams) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*ExampleParams, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ExampleParams, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ExampleParams, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*ExampleParams, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*ExampleParams, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultExampleParamsModel struct { + sqlc.CachedConn + table string + } + + ExampleParams struct { + Id int64 `db:"id"` // 主键ID + ProductId int64 `db:"product_id"` // 产品ID(直接关联到产品) + QueryParams string `db:"query_params"` // 查询params数据 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + } +) + +func newExampleParamsModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultExampleParamsModel { + return &defaultExampleParamsModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`example_params`", + } +} + +func (m *defaultExampleParamsModel) Insert(ctx context.Context, session sqlx.Session, data *ExampleParams) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + tycExampleParamsIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsIdPrefix, data.Id) + tycExampleParamsProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsProductIdPrefix, data.ProductId) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, exampleParamsRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.ProductId, data.QueryParams, data.DelState, data.Version, data.DeleteTime) + } + return conn.ExecCtx(ctx, query, data.ProductId, data.QueryParams, data.DelState, data.Version, data.DeleteTime) + }, tycExampleParamsIdKey, tycExampleParamsProductIdKey) +} + +func (m *defaultExampleParamsModel) FindOne(ctx context.Context, id int64) (*ExampleParams, error) { + tycExampleParamsIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsIdPrefix, id) + var resp ExampleParams + err := m.QueryRowCtx(ctx, &resp, tycExampleParamsIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", exampleParamsRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultExampleParamsModel) FindOneByProductId(ctx context.Context, productId int64) (*ExampleParams, error) { + tycExampleParamsProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsProductIdPrefix, productId) + var resp ExampleParams + err := m.QueryRowIndexCtx(ctx, &resp, tycExampleParamsProductIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `product_id` = ? and del_state = ? limit 1", exampleParamsRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, productId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultExampleParamsModel) Update(ctx context.Context, session sqlx.Session, newData *ExampleParams) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + tycExampleParamsIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsIdPrefix, data.Id) + tycExampleParamsProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsProductIdPrefix, data.ProductId) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, exampleParamsRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.DelState, newData.Version, newData.DeleteTime, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.DelState, newData.Version, newData.DeleteTime, newData.Id) + }, tycExampleParamsIdKey, tycExampleParamsProductIdKey) +} + +func (m *defaultExampleParamsModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *ExampleParams) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + tycExampleParamsIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsIdPrefix, data.Id) + tycExampleParamsProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsProductIdPrefix, data.ProductId) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, exampleParamsRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.DelState, newData.Version, newData.DeleteTime, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.ProductId, newData.QueryParams, newData.DelState, newData.Version, newData.DeleteTime, newData.Id, oldVersion) + }, tycExampleParamsIdKey, tycExampleParamsProductIdKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultExampleParamsModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *ExampleParams) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "ExampleParamsModel delete err : %+v", err) + } + return nil +} + +func (m *defaultExampleParamsModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultExampleParamsModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultExampleParamsModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*ExampleParams, error) { + + builder = builder.Columns(exampleParamsRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*ExampleParams + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleParamsModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ExampleParams, error) { + + builder = builder.Columns(exampleParamsRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*ExampleParams + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleParamsModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*ExampleParams, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(exampleParamsRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*ExampleParams + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultExampleParamsModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*ExampleParams, error) { + + builder = builder.Columns(exampleParamsRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*ExampleParams + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleParamsModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*ExampleParams, error) { + + builder = builder.Columns(exampleParamsRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*ExampleParams + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleParamsModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultExampleParamsModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultExampleParamsModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + tycExampleParamsIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsIdPrefix, id) + tycExampleParamsProductIdKey := fmt.Sprintf("%s%v", cacheTycExampleParamsProductIdPrefix, data.ProductId) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, tycExampleParamsIdKey, tycExampleParamsProductIdKey) + return err +} +func (m *defaultExampleParamsModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheTycExampleParamsIdPrefix, primary) +} +func (m *defaultExampleParamsModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", exampleParamsRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultExampleParamsModel) tableName() string { + return m.table +} diff --git a/deploy/script/gen_models.ps1 b/deploy/script/gen_models.ps1 index ea71dd1..42ae7b3 100644 --- a/deploy/script/gen_models.ps1 +++ b/deploy/script/gen_models.ps1 @@ -7,16 +7,16 @@ $TEMPLATE_DIR = "../template" # 表名列表 $tables = @( - "example", - "feature", - "global_notifications", - "order", - "product", - "product_feature", - "product_render", - "query", - "user", - "user_auth" + "example_params" + # "feature", + # "global_notifications", + # "order", + # "product", + # "product_feature", + # "product_render", + # "query", + # "user", + # "user_auth" ) # 为每个表生成模型 diff --git a/deploy/script/model/exampleModel.go b/deploy/script/model/exampleModel.go new file mode 100644 index 0000000..d041ea0 --- /dev/null +++ b/deploy/script/model/exampleModel.go @@ -0,0 +1,27 @@ +package model + +import ( + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlx" +) + +var _ ExampleModel = (*customExampleModel)(nil) + +type ( + // ExampleModel is an interface to be customized, add more methods here, + // and implement the added methods in customExampleModel. + ExampleModel interface { + exampleModel + } + + customExampleModel struct { + *defaultExampleModel + } +) + +// NewExampleModel returns a model for the database table. +func NewExampleModel(conn sqlx.SqlConn, c cache.CacheConf) ExampleModel { + return &customExampleModel{ + defaultExampleModel: newExampleModel(conn, c), + } +} diff --git a/deploy/script/model/exampleModel_gen.go b/deploy/script/model/exampleModel_gen.go new file mode 100644 index 0000000..9064d83 --- /dev/null +++ b/deploy/script/model/exampleModel_gen.go @@ -0,0 +1,434 @@ +// Code generated by goctl. DO NOT EDIT! + +package model + +import ( + "context" + "database/sql" + "fmt" + "strings" + + "time" + + "github.com/Masterminds/squirrel" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/stores/builder" + "github.com/zeromicro/go-zero/core/stores/cache" + "github.com/zeromicro/go-zero/core/stores/sqlc" + "github.com/zeromicro/go-zero/core/stores/sqlx" + "github.com/zeromicro/go-zero/core/stringx" + "tyc-server/common/globalkey" +) + +var ( + exampleFieldNames = builder.RawFieldNames(&Example{}) + exampleRows = strings.Join(exampleFieldNames, ",") + exampleRowsExpectAutoSet = strings.Join(stringx.Remove(exampleFieldNames, "`id`", "`create_time`", "`update_time`"), ",") + exampleRowsWithPlaceHolder = strings.Join(stringx.Remove(exampleFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" + + cacheTycExampleIdPrefix = "cache:tyc:example:id:" + cacheTycExampleApiIdPrefix = "cache:tyc:example:apiId:" + cacheTycExampleFeatureIdPrefix = "cache:tyc:example:featureId:" +) + +type ( + exampleModel interface { + Insert(ctx context.Context, session sqlx.Session, data *Example) (sql.Result, error) + FindOne(ctx context.Context, id int64) (*Example, error) + FindOneByApiId(ctx context.Context, apiId string) (*Example, error) + FindOneByFeatureId(ctx context.Context, featureId int64) (*Example, error) + Update(ctx context.Context, session sqlx.Session, data *Example) (sql.Result, error) + UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Example) error + Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error + SelectBuilder() squirrel.SelectBuilder + DeleteSoft(ctx context.Context, session sqlx.Session, data *Example) error + FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error) + FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error) + FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*Example, error) + FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Example, error) + FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Example, int64, error) + FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Example, error) + FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Example, error) + Delete(ctx context.Context, session sqlx.Session, id int64) error + } + + defaultExampleModel struct { + sqlc.CachedConn + table string + } + + Example struct { + Id int64 `db:"id"` // 主键ID + CreateTime time.Time `db:"create_time"` // 创建时间 + UpdateTime time.Time `db:"update_time"` // 更新时间 + DeleteTime sql.NullTime `db:"delete_time"` // 删除时间 + DelState int64 `db:"del_state"` // 删除状态 + Version int64 `db:"version"` // 版本号 + ApiId string `db:"api_id"` // API标识 + FeatureId int64 `db:"feature_id"` // 关联feature表的ID + Content string `db:"content"` // 内容 + } +) + +func newExampleModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultExampleModel { + return &defaultExampleModel{ + CachedConn: sqlc.NewConn(conn, c), + table: "`example`", + } +} + +func (m *defaultExampleModel) Insert(ctx context.Context, session sqlx.Session, data *Example) (sql.Result, error) { + data.DelState = globalkey.DelStateNo + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) + tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, data.Id) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?)", m.table, exampleRowsExpectAutoSet) + if session != nil { + return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ApiId, data.FeatureId, data.Content) + } + return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ApiId, data.FeatureId, data.Content) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) +} + +func (m *defaultExampleModel) FindOne(ctx context.Context, id int64) (*Example, error) { + tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, id) + var resp Example + err := m.QueryRowCtx(ctx, &resp, tycExampleIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", exampleRows, m.table) + return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo) + }) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultExampleModel) FindOneByApiId(ctx context.Context, apiId string) (*Example, error) { + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, apiId) + var resp Example + err := m.QueryRowIndexCtx(ctx, &resp, tycExampleApiIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `api_id` = ? and del_state = ? limit 1", exampleRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, apiId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultExampleModel) FindOneByFeatureId(ctx context.Context, featureId int64) (*Example, error) { + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, featureId) + var resp Example + err := m.QueryRowIndexCtx(ctx, &resp, tycExampleFeatureIdKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) { + query := fmt.Sprintf("select %s from %s where `feature_id` = ? and del_state = ? limit 1", exampleRows, m.table) + if err := conn.QueryRowCtx(ctx, &resp, query, featureId, globalkey.DelStateNo); err != nil { + return nil, err + } + return resp.Id, nil + }, m.queryPrimary) + switch err { + case nil: + return &resp, nil + case sqlc.ErrNotFound: + return nil, ErrNotFound + default: + return nil, err + } +} + +func (m *defaultExampleModel) Update(ctx context.Context, session sqlx.Session, newData *Example) (sql.Result, error) { + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return nil, err + } + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) + tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, data.Id) + return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, exampleRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) +} + +func (m *defaultExampleModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Example) error { + + oldVersion := newData.Version + newData.Version += 1 + + var sqlResult sql.Result + var err error + + data, err := m.FindOne(ctx, newData.Id) + if err != nil { + return err + } + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) + tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, data.Id) + sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, exampleRowsWithPlaceHolder) + if session != nil { + return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id, oldVersion) + } + return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ApiId, newData.FeatureId, newData.Content, newData.Id, oldVersion) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) + if err != nil { + return err + } + updateCount, err := sqlResult.RowsAffected() + if err != nil { + return err + } + if updateCount == 0 { + return ErrNoRowsUpdate + } + + return nil +} + +func (m *defaultExampleModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *Example) error { + data.DelState = globalkey.DelStateYes + data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true} + if err := m.UpdateWithVersion(ctx, session, data); err != nil { + return errors.Wrapf(errors.New("delete soft failed "), "ExampleModel delete err : %+v", err) + } + return nil +} + +func (m *defaultExampleModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field") + } + + builder = builder.Columns("IFNULL(SUM(" + field + "),0)") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp float64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultExampleModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) { + + if len(field) == 0 { + return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field") + } + + builder = builder.Columns("COUNT(" + field + ")") + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return 0, err + } + + var resp int64 + err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return 0, err + } +} + +func (m *defaultExampleModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*Example, error) { + + builder = builder.Columns(exampleRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql() + if err != nil { + return nil, err + } + + var resp []*Example + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Example, error) { + + builder = builder.Columns(exampleRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Example + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*Example, int64, error) { + + total, err := m.FindCount(ctx, builder, "id") + if err != nil { + return nil, 0, err + } + + builder = builder.Columns(exampleRows) + + if orderBy == "" { + builder = builder.OrderBy("id DESC") + } else { + builder = builder.OrderBy(orderBy) + } + + if page < 1 { + page = 1 + } + offset := (page - 1) * pageSize + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, total, err + } + + var resp []*Example + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, total, nil + default: + return nil, total, err + } +} + +func (m *defaultExampleModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*Example, error) { + + builder = builder.Columns(exampleRows) + + if preMinId > 0 { + builder = builder.Where(" id < ? ", preMinId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Example + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*Example, error) { + + builder = builder.Columns(exampleRows) + + if preMaxId > 0 { + builder = builder.Where(" id > ? ", preMaxId) + } + + query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql() + if err != nil { + return nil, err + } + + var resp []*Example + err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...) + switch err { + case nil: + return resp, nil + default: + return nil, err + } +} + +func (m *defaultExampleModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error { + + return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { + return fn(ctx, session) + }) + +} + +func (m *defaultExampleModel) SelectBuilder() squirrel.SelectBuilder { + return squirrel.Select().From(m.table) +} +func (m *defaultExampleModel) Delete(ctx context.Context, session sqlx.Session, id int64) error { + data, err := m.FindOne(ctx, id) + if err != nil { + return err + } + + tycExampleApiIdKey := fmt.Sprintf("%s%v", cacheTycExampleApiIdPrefix, data.ApiId) + tycExampleFeatureIdKey := fmt.Sprintf("%s%v", cacheTycExampleFeatureIdPrefix, data.FeatureId) + tycExampleIdKey := fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, id) + _, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { + query := fmt.Sprintf("delete from %s where `id` = ?", m.table) + if session != nil { + return session.ExecCtx(ctx, query, id) + } + return conn.ExecCtx(ctx, query, id) + }, tycExampleApiIdKey, tycExampleFeatureIdKey, tycExampleIdKey) + return err +} +func (m *defaultExampleModel) formatPrimary(primary interface{}) string { + return fmt.Sprintf("%s%v", cacheTycExampleIdPrefix, primary) +} +func (m *defaultExampleModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error { + query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", exampleRows, m.table) + return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo) +} + +func (m *defaultExampleModel) tableName() string { + return m.table +}