package services import ( "bytes" "crypto/md5" "encoding/json" "errors" "eta/eta_data_init/models" "eta/eta_data_init/utils" "fmt" "github.com/shopspring/decimal" "github.com/xuri/excelize/v2" "io/ioutil" "net/http" "os" "path/filepath" "reflect" "sort" "strconv" "strings" "time" ) //初始化计算指标数据 //classifyId:=685 const ( HZ_DATA_API = "https://hzdataapi.hzinsights.com/hzdataapi/" ClassifyId = 685 ) func InitCalculateIndex() { //读取基础指标 var err error defer func() { if err != nil { fmt.Println("InitBaseIndexData Err:" + err.Error()) } }() //读取excel path, err := filepath.Abs(os.Args[0]) if err != nil { fmt.Println(err) } dir := filepath.Dir(path) fmt.Println("dir:" + dir) dataPath := dir + "/docs/逸诺指标库(基础).xlsx" fmt.Println("dataPath:" + dataPath) f, err := excelize.OpenFile(dataPath) if err != nil { fmt.Println(err) return } defer func() { // Close the spreadsheet. if err := f.Close(); err != nil { fmt.Println(err) } }() rows, err := f.GetRows("edb_info") if err != nil { fmt.Println(err) return } hzMethod := "edb_index/detail" edbLibIndexMethod := "/edb_info/detail" var needAddIndexArr []string needAddIndexMap := make(map[string]string) edbLibIndexMap := make(map[string]int) for rk, row := range rows { if rk <= 0 { continue } if rk%10 == 0 { time.Sleep(3 * time.Second) } var indexCode string for ck, colCell := range row { switch ck { case 0: indexCode = colCell } } fmt.Println(rk, indexCode) if indexCode == "" { fmt.Println("指标编码不能为空") return } params := make(map[string]interface{}) params["EdbCode"] = indexCode result, err := hzDataHttpPost(hzMethod, params) if err != nil { fmt.Println("hzDataHttpPost Err:" + err.Error()) return } utils.FileLog.Info("hzDataHttpPost:" + string(result)) resp := new(models.EdbInfoResp) err = json.Unmarshal([]byte(result), &resp) if err != nil { fmt.Println("json.Unmarshal Err:" + err.Error()) return } if resp.Ret != 200 && !strings.Contains(resp.ErrMsg, "QuerySeter") { fmt.Println("resp Err:" + resp.ErrMsg) return } //指标信息不存在 if resp.Data.EdbInfoId <= 0 { fmt.Println("指标:" + indexCode + ";不存在") f.SetCellStr("edb_info", "H"+strconv.Itoa(rk+1), "不存在") continue } //判断是否存在计算指标 if len(resp.Data.CalculateList) <= 0 { f.SetCellStr("edb_info", "H"+strconv.Itoa(rk+1), "不存在") continue } //存在计算指标 for _, cv := range resp.Data.CalculateList { //计算指标所依赖的基础指标 var total int for _, bv := range cv.BaseEdbInfoCode { //判断基础指标是否存在 indexMap := make(map[string]interface{}) indexMap["EdbCode"] = bv.FromEdbCode result, err := PostEdbLib(indexMap, edbLibIndexMethod) if err != nil { utils.FileLog.Info("获取计算指标所依赖的基础指标失败:" + err.Error() + " result:" + string(result)) return } indexResp := new(models.EdbInfoResp) err = json.Unmarshal(result, &indexResp) if err != nil { utils.FileLog.Info("json.Unmarshal 获取计算指标所依赖的基础指标失败:" + err.Error()) return } if indexResp.Ret != 200 && indexResp.ErrCode != "400" { fmt.Println("获取计算指标所依赖的基础指标失败 Err:" + indexResp.Msg) return } if indexResp.Data.EdbInfoId > 0 { edbLibIndexMap[bv.FromEdbCode] = indexResp.Data.EdbInfoId total++ } } if total == len(cv.BaseEdbInfoCode) { if _, ok := needAddIndexMap[cv.EdbCode]; !ok { needAddIndexArr = append(needAddIndexArr, cv.EdbCode) needAddIndexMap[cv.EdbCode] = cv.EdbCode } } } } f.Save() fmt.Println("calculate len:", len(needAddIndexArr)) time.Sleep(30 * time.Second) hzIndexMethod := "edb_index/item" hzCalculateIndexMethod := "edb_info_calculate/item" edbLibIndexMethod = "edb_info/copy/from/hz" edbLibCalculateIndexMethod := "edb_info/copy/calculate/from/hz" for k, v := range needAddIndexArr { //需要同步的计算指标 fmt.Println(k, v) params := make(map[string]interface{}) params["EdbCode"] = v hzResult, err := hzDataHttpPost(hzIndexMethod, params) if err != nil { fmt.Println("hzDataHttpPost Err:" + err.Error()) return } hzResp := new(models.EdbInfoItemResp) err = json.Unmarshal([]byte(hzResult), &hzResp) if err != nil { fmt.Println("json.Unmarshal Err:" + err.Error()) return } if hzResp.Ret != 200 { fmt.Println("resp Err:" + hzResp.ErrMsg) return } edbInfo := hzResp.Data //新增指标信息 indexMap := make(map[string]interface{}) indexMap["EdbInfoType"] = edbInfo.EdbInfoType indexMap["SourceName"] = edbInfo.SourceName indexMap["Source"] = edbInfo.Source indexMap["EdbCode"] = edbInfo.EdbCode indexMap["EdbName"] = edbInfo.EdbName indexMap["EdbNameEn"] = edbInfo.EdbNameEn indexMap["EdbNameSource"] = edbInfo.EdbNameSource indexMap["Frequency"] = edbInfo.Frequency indexMap["Unit"] = edbInfo.Unit indexMap["UnitEn"] = edbInfo.UnitEn indexMap["StartDate"] = edbInfo.StartDate indexMap["EndDate"] = edbInfo.EndDate indexMap["ClassifyId"] = ClassifyId indexMap["SysUserId"] = 0 indexMap["SysUserRealName"] = "" indexMap["UniqueCode"] = edbInfo.UniqueCode indexMap["CreateTime"] = time.Now() indexMap["ModifyTime"] = time.Now() indexMap["MinValue"] = edbInfo.MinValue indexMap["MaxValue"] = edbInfo.MaxValue indexMap["CalculateFormula"] = edbInfo.CalculateFormula indexMap["EdbType"] = edbInfo.EdbType indexMap["IsUpdate"] = 1 indexMap["Sort"] = edbInfo.Sort indexMap["LatestDate"] = edbInfo.LatestDate indexMap["LatestValue"] = edbInfo.LatestValue indexMap["MoveType"] = edbInfo.MoveType indexMap["MoveFrequency"] = edbInfo.MoveFrequency indexMap["NoUpdate"] = edbInfo.NoUpdate indexMap["ServerUrl"] = edbInfo.ServerUrl indexMap["ChartImage"] = edbInfo.ChartImage indexMap["Calendar"] = edbInfo.Calendar indexMap["DataDateType"] = edbInfo.DataDateType edbLibResult, err := PostEdbLib(indexMap, edbLibIndexMethod) if err != nil { utils.FileLog.Info("新增计算指标失败:" + err.Error() + " result:" + string(edbLibResult)) return } indexBaseResp := new(models.EdbInfoResp) err = json.Unmarshal(edbLibResult, &indexBaseResp) if err != nil { fmt.Println("edbLibResult json.Unmarshal Err:" + err.Error()) return } if indexBaseResp.Ret != 200 { fmt.Println("PostEdbLib resp Err:" + hzResp.ErrMsg) return } //新增计算指标映射关系 calculateParams := make(map[string]interface{}) calculateParams["EdbCode"] = v hzResult, err = hzDataHttpPost(hzCalculateIndexMethod, calculateParams) if err != nil { fmt.Println("hzDataHttpPost calculate Err:" + err.Error()) return } hzCalculateResp := new(models.EdbInfoCalculateMappingResp) err = json.Unmarshal([]byte(hzResult), &hzCalculateResp) if err != nil { fmt.Println("calculate json.Unmarshal Err:" + err.Error()) return } if hzResp.Ret != 200 { fmt.Println("calculate resp Err:" + hzResp.ErrMsg) return } for _, cv := range hzCalculateResp.Data { //获取FromIndex var fromEdbInfoId int fromEdbInfoId = edbLibIndexMap[cv.FromEdbCode] //新增指标信息 indexCalculateMap := make(map[string]interface{}) indexCalculateMap["EdbInfoId"] = indexBaseResp.Data.EdbInfoId indexCalculateMap["Source"] = cv.Source indexCalculateMap["SourceName"] = cv.SourceName indexCalculateMap["EdbCode"] = cv.EdbCode indexCalculateMap["FromEdbInfoId"] = fromEdbInfoId indexCalculateMap["FromEdbCode"] = cv.FromEdbCode indexCalculateMap["FromEdbName"] = cv.FromEdbName indexCalculateMap["FromSource"] = cv.FromSource indexCalculateMap["FromSourceName"] = cv.FromSourceName indexCalculateMap["MoveValue"] = cv.MoveValue indexCalculateMap["Sort"] = cv.Sort indexCalculateMap["CreateTime"] = time.Now() indexCalculateMap["ModifyTime"] = time.Now() indexCalculateMap["FromTag"] = cv.FromTag edbLibResult, err := PostEdbLib(indexCalculateMap, edbLibCalculateIndexMethod) if err != nil { utils.FileLog.Info("新增计算指标映射关系失败:" + err.Error() + " result:" + string(edbLibResult)) return } baseResp := new(models.BaseResponse) err = json.Unmarshal([]byte(edbLibResult), &baseResp) if err != nil { fmt.Println("edbLibResult mapping json.Unmarshal Err:" + err.Error()) return } if baseResp.Ret != 200 { fmt.Println("PostEdbLib mapping resp Err:" + hzResp.ErrMsg) return } } time.Sleep(1 * time.Second) } } func hzDataHttpPost(method string, postDataMap map[string]interface{}) (result string, err error) { bytesData, err := handlePostData(postDataMap) if err != nil { return } client := &http.Client{} req, err := http.NewRequest("POST", HZ_DATA_API+method, bytes.NewReader(bytesData)) if err != nil { return "", err } req.Header.Set("content-type", "application/json") resp, err := client.Do(req) if err != nil { return "", err } body, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } result = string(body) return } // handlePostData 处理post请求数据 func handlePostData(postDataMap map[string]interface{}) (bytesData []byte, err error) { postDataMap["nonce_str"] = utils.GetRandString(16) // 随机字符串 postDataMap["timestamp"] = time.Now().Unix() //当前格林威治时间,int64类型 postDataMap["appid"] = utils.APPID //当前格林威治时间,int64类型 // 待签名数据 signData := convertParamInterface(postDataMap) sign, err := getSignData(signData) if err != nil { return } postDataMap["sign"] = sign //签名 bytesData, err = json.Marshal(postDataMap) return } // 将请求传入的数据格式转换成签名需要的格式(目前只能处理简单的类型,数组、对象暂不支持) func convertParamInterface(params map[string]interface{}) (signData map[string]string) { signData = make(map[string]string) for key := range params { val := `` //fmt.Println("key", key, ";val:", params[key], ";type:", reflect.TypeOf(params[key])) //signData[key] = params[key][0] tmpVal := params[key] switch reflect.TypeOf(tmpVal).Kind() { case reflect.String: val = fmt.Sprint(tmpVal) case reflect.Int, reflect.Int16, reflect.Int64, reflect.Int32, reflect.Int8: val = fmt.Sprint(tmpVal) case reflect.Uint, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint64: val = fmt.Sprint(tmpVal) case reflect.Bool: val = fmt.Sprint(tmpVal) case reflect.Float64: decimalNum := decimal.NewFromFloat(tmpVal.(float64)) val = decimalNum.String() //val = strconv.FormatFloat(tmpVal.(float64), 'E', -1, 64) //float64 case reflect.Float32: decimalNum := decimal.NewFromFloat32(tmpVal.(float32)) val = decimalNum.String() } signData[key] = val } return signData } // getSignData 获取参数签名 func getSignData(postData map[string]string) (sign string, err error) { appid := utils.APPID if appid == "" { err = errors.New("参数异常,缺少appid") return } secret := utils.SECRET if secret == "" { err = errors.New("参数异常,缺少secret") return } if postData["nonce_str"] == "" { err = errors.New("参数异常,缺少随机字符串") return } if postData["timestamp"] == "" { err = errors.New("参数异常,缺少时间戳") return } //先取出除sign外的所有的提交的参数key var keys []string for k := range postData { if k != "sign" { keys = append(keys, k) } } //1,根据参数名称的ASCII码表的顺序排序 sort.Strings(keys) //2 根据排序后的参数名称,取出对应的值,并拼接字符串 var signStr string for _, v := range keys { signStr += v + "=" + postData[v] + "&" } //3,全转小写(md5(拼装的字符串后+分配给你的app_secret)) //sign := strings.ToLower(fmt.Sprintf("%x", md5.Sum([]byte(strings.Trim(signStr, "&")+key)))) //md5.Sum([]byte(signStr+"key="+key)) 这是md5加密出来后的每个字符的ascall码,需要再转换成对应的字符 //3,全转大写(md5(拼装的字符串后+分配给你的app_secret)) sign = strings.ToUpper(fmt.Sprintf("%x", md5.Sum([]byte(signStr+"secret="+secret)))) return }