package jxutils import ( "bytes" "context" "crypto/aes" "crypto/md5" "encoding/base64" "fmt" "io/ioutil" "math" "math/rand" "regexp" "strings" "time" "git.rosy.net.cn/baseapi" "git.rosy.net.cn/baseapi/platformapi/autonavi" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/baseapi/utils/routinepool" "git.rosy.net.cn/jx-callback/business/jxutils/excel" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/api" "github.com/qiniu/api.v7/storage" ) var ( routinePool *routinepool.Pool skuNamePat *regexp.Regexp emailPat *regexp.Regexp orderNoBeginTimestamp int64 resourceTypeMap = map[int][]string{ model.VendorIDQiNiuCloud: []string{ "image.jxc4.com", }, model.VendorIDJD: []string{ "img30.360buyimg.com", }, model.VendorIDEBAI: []string{ "image-star.elemecdn.com", }, model.VendorIDYB: []string{ "pospalstoreimg.area27.pospal.cn", }, } ) const fileExt = ".xlsx" func init() { rand.Seed(time.Now().Unix()) routinePool = routinepool.New(1000, 1000) // Go regex does not support lookarounds. // https://stackoverflow.com/questions/38933898/error-parsing-regexp-invalid-or-unsupported-perl-syntax skuNamePat = regexp.MustCompile(`([\((\[【][^\((\[【\))\]】]*[\))\]】])?(.*?)([((].*[))])?\s*约?([1-9][\d\.]*)(g|G|kg|kG|Kg|KG|l|L|ml|mL|Ml|ML|克)\s*([((].*[))])?\s*(?:\/|/|)\s*([^\s()()]{0,2})(\s.*)?$\s*([((].*[))])?$`) emailPat = regexp.MustCompile(`[A-Za-z0-9_\-.]+@(?:[A-Za-z0-9_\-]+\.)+[A-Za-z]+`) orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix() } func GetSaleStoreIDFromAfsOrder(order *model.AfsOrder) (retVal int) { if order.JxStoreID > 0 { return order.JxStoreID } return order.StoreID } func GetSkuIDFromOrderSkuFinancial(sku *model.OrderSkuFinancial) (skuID int) { if sku.JxSkuID > 0 { return sku.JxSkuID } return sku.SkuID } func SplitUniversalOrderID(universalOrderID string) (orderID string, vendorID int) { index := strings.Index(universalOrderID, "|") if index != -1 { orderID = universalOrderID[:index] vendorID = int(utils.Str2Int64(universalOrderID[index+1:])) } else { if vendorID = GetPossibleVendorIDFromVendorOrderID(universalOrderID); vendorID == model.VendorIDUnknown { // globals.SugarLogger.Errorf("unkown order type:%v", universalOrderID) panic(fmt.Sprintf("unkown order type, orderID:%s", universalOrderID)) } orderID = universalOrderID } return orderID, vendorID } func GetPossibleVendorIDFromVendorOrderID(vendorOrderID string) (vendorID int) { vendorID = model.VendorIDUnknown if vendorOrderIDInt64 := utils.Str2Int64WithDefault(vendorOrderID, 0); vendorOrderIDInt64 > 0 { orderIDLen := len(vendorOrderID) // 5287873015048 13 wsc // 15380342248732 14 old ebai order // 800402581000221 15,16 jd order // 33437032333978492 17 mtwm order // 3022716176275221584 19 elm order, new ebai order // 京东到家从2020年开始订单号的长度都会在现有基础上加一位,订单号的前两位取的是当年的最后两位数(如:2020取的20),以适应业务的发展。 // 改造点: // 1、订单号位数变化,由原有15位数增加1位数调整为16位数,对接商家需检查是否有对订单号位数做长度校验。 // 2、第一位数字发生变化,由原来9开头调整为当年年份后两位数如:2020年订单开头为20; if orderIDLen == len("925265130002541") || orderIDLen == len("1925265130002541") { vendorID = model.VendorIDJD } else if orderIDLen == len("3022716176275221584") { // vendorID = model.VendorIDELM vendorID = model.VendorIDEBAI // 饿百零售开放平台订单接口中订单ID“order_id”字段长度将调整为19位,和饿了么订单ID“eleme_order_id”字段格式保持一致。 } else if orderIDLen == len("15380342248732") { if vendorOrderID[:2] == "88" { vendorID = model.VendorIDJX } else { vendorID = model.VendorIDEBAI } } else if orderIDLen == len("33437032333978492") { vendorID = model.VendorIDMTWM } else if orderIDLen == len("5287873015048") { vendorID = model.VendorIDWSC } else if orderIDLen == len("1000004390") { vendorID = model.VendorIDJX } else if orderIDLen == len("124557362562000001") || orderIDLen == len("13153183146800000100") { vendorID = model.VendorIDJDShop } } return vendorID } func GenRand6() (num int) { return utils.Str2Int(fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))) } func GenOrderNo() (orderNo int64) { var prefix = utils.Str2Int64(time.Now().Format("20060102")) const randPartNum = 1000 orderNo = time.Now().Unix() - orderNoBeginTimestamp orderNo = orderNo * randPartNum md5Bytes := md5.Sum([]byte(utils.GetUUID())) randPart := 0 for k, v := range md5Bytes { randPart += int(v) << ((k % 3) * 8) } orderNo += int64(randPart % randPartNum) orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix return orderNo } func GenJobOrderNo() (orderNo int64) { const prefix = 88 const randPartNum = 1000 orderNo = time.Now().Unix() - orderNoBeginTimestamp orderNo = orderNo * randPartNum md5Bytes := md5.Sum([]byte(utils.GetUUID())) randPart := 0 for k, v := range md5Bytes { randPart += int(v) << ((k % 3) * 8) } orderNo += int64(randPart % randPartNum) orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix return orderNo } func GenBillID() (billID int64) { const prefix = 66 const randPartNum = 100 billID = time.Now().Unix() - orderNoBeginTimestamp billID = billID * randPartNum md5Bytes := md5.Sum([]byte(utils.GetUUID())) randPart := 0 for k, v := range md5Bytes { randPart += int(v) << ((k % 3) * 8) } billID += int64(randPart % randPartNum) billID += int64(math.Pow10(int(math.Log10(float64(billID)))+1)) * prefix return billID } func GenGroupID() (groupID int64) { const randPartNum = 100 groupID = time.Now().Unix() - orderNoBeginTimestamp groupID = groupID * randPartNum md5Bytes := md5.Sum([]byte(utils.GetUUID())) randPart := 0 for k, v := range md5Bytes { randPart += int(v) << ((k % 3) * 8) } groupID += int64(randPart % randPartNum) groupID += int64(math.Pow10(int(math.Log10(float64(groupID))) + 1)) return groupID } func GenAfsOrderNo() (orderNo int64) { const prefix = 80 const randPartNum = 100 orderNo = time.Now().Unix() - orderNoBeginTimestamp orderNo = orderNo * randPartNum md5Bytes := md5.Sum([]byte(utils.GetUUID())) randPart := 0 for k, v := range md5Bytes { randPart += int(v) << ((k % 3) * 8) } orderNo += int64(randPart % randPartNum) orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix return orderNo } func GetPossibleVendorIDFromAfsOrderID(afsOrderID string) (vendorID int) { vendorID = model.VendorIDUnknown if afsOrderIDInt64 := utils.Str2Int64WithDefault(afsOrderID, 0); afsOrderIDInt64 > 0 { orderIDLen := len(afsOrderID) if orderIDLen == len("22586438") { // 8 vendorID = model.VendorIDJD } else if orderIDLen == len("1413138834") { // 10 vendorID = model.VendorIDEBAI } else if orderIDLen == len("29488498752") { // 11 vendorID = model.VendorIDMTWM } } return vendorID } func ComposeUniversalOrderID(orderID string, vendorID int) string { // return fmt.Sprintf("%s|%d", orderID, vendorID) return orderID // 当前用长度就能区分,先不加上vendorID } // distance单位为米 func ConvertDistanceToLogLat(lng, lat, distance, angle float64) (newLng, newLat float64) { oneDu := 111319.55 // 单位为米 newLng = lng + (distance*math.Sin(angle*math.Pi/180))/(oneDu*math.Cos(lat*math.Pi/180)) //将距离转换成经度的计算公式 newLat = lat + (distance*math.Cos(angle*math.Pi/180))/oneDu //将距离转换成纬度的计算公式 return newLng, newLat } // 返回结果单元为公里 func EarthDistance(lng1, lat1, lng2, lat2 float64) float64 { radius := 6378.137 rad := math.Pi / 180.0 lat1 = lat1 * rad lng1 = lng1 * rad lat2 = lat2 * rad lng2 = lng2 * rad theta := lng2 - lng1 dist := math.Acos(math.Sin(lat1)*math.Sin(lat2) + math.Cos(lat1)*math.Cos(lat2)*math.Cos(theta)) if dist < 0 { dist = 0 } return dist * radius } // 返回结果单元为公里 func WalkingDistance(lng1, lat1, lng2, lat2 float64) (distance float64) { if distance = api.AutonaviAPI.WalkingDistance(lng1, lat1, lng2, lat2); distance == 0 { distance = EarthDistance(lng1, lat1, lng2, lat2) * 1.4 } else { distance /= 1000 } return distance } func StandardCoordinate2Int(value float64) int { return int(math.Round(value * 1000000)) } func IntCoordinate2Standard(value int) float64 { return float64(value) / 1000000 } func IntCoordinate2MarsStandard(gpsLng, gpsLat int, coordinateType int) (marsLng, marsLat float64, err error) { marsLng = IntCoordinate2Standard(gpsLng) marsLat = IntCoordinate2Standard(gpsLat) coordSys := "" switch coordinateType { case model.CoordinateTypeGPS: coordSys = autonavi.CoordSysGPS case model.CoordinateTypeMars: return marsLng, marsLat, nil case model.CoordinateTypeBaiDu: coordSys = autonavi.CoordSysBaidu case model.CoordinateTypeMapbar: coordSys = autonavi.CoordSysMapbar default: panic(fmt.Sprintf("known coordinate type:%d", coordinateType)) } return api.AutonaviAPI.CoordinateConvert(marsLng, marsLat, coordSys) } func IntPrice2Standard(value int64) float64 { return float64(value) / 100 } func StandardPrice2Int(value float64) int64 { return int64(math.Round(value * 100)) } func IntPrice2StandardString(value int64) string { return fmt.Sprintf("%.2f", IntPrice2Standard(value)) } func IntPrice2StandardCurrencyString(value int64) string { return fmt.Sprintf("¥%.2f", IntPrice2Standard(value)) } func CallMsgHandler(handler func(), primaryID string) { routinePool.CallFun(func() { handler() }, primaryID) } func CallMsgHandlerAsync(handler func(), primaryID string) { routinePool.CallFunAsync(func() { handler() }, primaryID) } func GetNameAndUnitFromSkuName(fullName string) (name string, unit string) { unit = "份" index := strings.Index(fullName, "/") if index >= 0 { name = fullName[:index] unitTmp := []rune(fullName[index+1:]) if len(unitTmp) >= 1 { unit = string(unitTmp[:1]) } } else { name = fullName } return name, unit } func MapValue2Scope(value, fromMin, fromMax, toMin, toMax int64) int64 { if value < fromMin { value = fromMin } if value > fromMax { value = fromMax } return int64(math.Round(float64(value-fromMin)/float64(fromMax-fromMin)*float64(toMax-toMin) + float64(toMin))) } func Errs2Str(sep string, errs ...error) (retVal string) { if sep == "" { sep = "\n" } for _, err := range errs { if err != nil { retVal += err.Error() + sep } } return retVal } func IntWeight2Float(weight int) float32 { return float32(weight) / 1000.0 } func FloatWeight2Int(weight float32) int { return int(math.Round(float64(weight * 1000))) } func ComposeSkuNameOriginal(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int) (skuName string) { strBuilder := &strings.Builder{} if prefix != "" { strBuilder.WriteString("[") strBuilder.WriteString(prefix) strBuilder.WriteString("]") } skuName += name strBuilder.WriteString(name) if unit == "份" { strBuilder.WriteString("约") } if unit != "" { strBuilder.WriteString(ComposeSkuSpec(spec_quality, spec_unit)) strBuilder.WriteString("/") strBuilder.WriteString(unit) } if comment != "" { strBuilder.WriteString("(") strBuilder.WriteString(comment) strBuilder.WriteString(")") } skuName = strBuilder.String() if maxLen > 0 { skuName = utils.LimitUTF8StringLen(skuName, maxLen) } return skuName } func ComposeSkuNameForJds(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int) (skuName string) { strBuilder := &strings.Builder{} if prefix != "" { strBuilder.WriteString("[") strBuilder.WriteString(prefix) strBuilder.WriteString("]") } skuName += name strBuilder.WriteString(name) if comment != "" { strBuilder.WriteString(" ") strBuilder.WriteString(comment) } if unit == "份" { strBuilder.WriteString("约") } if unit != "" { strBuilder.WriteString(ComposeSkuSpec(spec_quality, spec_unit)) } skuName = strBuilder.String() if maxLen > 0 { skuName = utils.LimitUTF8StringLen(skuName, maxLen) } return skuName } func ComposeSkuName(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) { if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil { if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { skuName = exPrefix } } skuName += ComposeSkuNameOriginal(prefix, name, comment, unit, spec_quality, spec_unit, maxLen) return skuName } func ComposeSkuNameSync(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) { if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil { if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { skuName = exPrefix } if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 { skuName = "" } } skuName += ComposeSkuNameOriginal(prefix, name, comment, unit, spec_quality, spec_unit, maxLen) return skuName } func ComposeSkuNameSync2(prefix, name, comment, unit string, spec_quality float32, spec_unit string, maxLen int, exPrefix string, exPrefixBegin, exPrefixEnd *time.Time) (skuName string) { if exPrefix != "" && exPrefixBegin != nil && exPrefixEnd != nil { if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { skuName = exPrefix } if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 { skuName = "" } } skuName += ComposeSkuNameForJds(prefix, name, comment, unit, spec_quality, spec_unit, maxLen) return skuName } func ComposeSpuName(prefix, name string, maxLen int) (spuName string) { if prefix != "" { spuName = "[" + prefix + "]" } spuName += name return utils.LimitUTF8StringLen(spuName, maxLen) } func ComposeSkuSpec(spec_quality float32, spec_unit string) (spec string) { if spec_unit != "" { if math.Round(float64(spec_quality)) == float64(spec_quality) || (spec_unit != "L" && spec_unit != "kg") { spec = fmt.Sprintf("%d", int(spec_quality)) } else { spec = strings.TrimRight(fmt.Sprintf("%.2f", spec_quality), "0.") } spec += spec_unit } return spec } // 1:商品特殊前缀 // 2:商品名字 // 3:商品说明1(可缺失) // 4:质量数字 // 5:质量单位 // 6:商品说明2(可缺失) // 7:商品单位 // 8:商品说明3(可缺失) func SplitSkuName(skuName string) (prefix, name, comment, specUnit, unit string, specQuality float32) { searchResult := skuNamePat.FindStringSubmatch(skuName) if searchResult != nil { if searchResult[3] != "" { comment = searchResult[3] } else if searchResult[6] != "" { comment = searchResult[6] } else if searchResult[8] != "" { comment = searchResult[8] } else if searchResult[9] != "" { comment = searchResult[9] } comment = TrimDecorationChar(comment) name = TrimDecorationChar(searchResult[2]) // if comment != "" { // // if utf8.RuneCountInString(comment) <= 5 { // // name += "-" + comment // // comment = "" // // } // } specUnit = strings.ToLower(strings.Replace(searchResult[5], "克", "g", -1)) if specUnit == "l" { specUnit = "L" } if searchResult[7] == "" { unit = "份" } else { unit = searchResult[7] } specQuality = float32(utils.Str2Float64(searchResult[4])) prefix = TrimDecorationChar(searchResult[1]) } return prefix, name, comment, specUnit, unit, specQuality } // https://my.oschina.net/hyller/blog/700414 func CalUpcCheckSum(upc12 int64) (checkSum int) { var sum [2]int for i := 0; i < 12; i++ { base := int64(math.Pow10(i)) sum[i%2] += int((upc12 / base) % 10) } sum[0] *= 3 return (10 - (sum[0]+sum[1])%10) % 10 } func IsUpcValid(upc string) bool { if len(upc) != 13 { return false } upcInt := utils.Str2Int64WithDefault(upc, 0) checkSum := CalUpcCheckSum(upcInt / 10) return int(utils.Str2Int64(upc[12:])) == checkSum } func GenFakeUPC(skuID int) string { id := int64(skuID) + 666600000000 return fmt.Sprintf("%012d%d", id, CalUpcCheckSum(id)) } func MakeValidationMapFromSlice(validValues []string, flag int) map[string]int { retVal := make(map[string]int) for _, v := range validValues { retVal[v] = flag } return retVal } func ComposeQiniuResURL(key string) string { return "http://image.jxc4.com/" + key } func IsLegalMobileNumber(num int64) bool { return num >= 13000000000 && num <= 19999999999 } func TrimDecorationChar(value string) string { return strings.Trim(value, " \t\n[]()【】()-_——") } func BatchStr2Time(strTime ...string) (timeList []time.Time, err error) { timeList = make([]time.Time, len(strTime)) for k, v := range strTime { if v == "" { timeList[k] = utils.DefaultTimeValue } else { if timeList[k], err = utils.TryStr2Time(v); err != nil { return nil, err } } } return timeList, nil } // strAndObjAddPairs必须按字符串1,转换地址1,字符串2,转换地址2这样的格式传递 func Strings2Objs(strAndObjAddPairs ...interface{}) (err error) { str := "" for k, v := range strAndObjAddPairs { if k%2 == 0 { str, _ = v.(string) } else if str != "" { if err = utils.UnmarshalUseNumber([]byte(str), v); err != nil { return err } } } return nil } func RefreshAfsOrderSkuRelated(afsOrder *model.AfsOrder) *model.AfsOrder { afsOrder.SkuUserMoney = 0 afsOrder.PmSkuSubsidyMoney = 0 for _, orderSku := range afsOrder.Skus { if orderSku.SkuID > math.MaxInt32 { orderSku.SkuID = orderSku.JxSkuID } afsOrder.SkuUserMoney += orderSku.UserMoney afsOrder.PmSkuSubsidyMoney += orderSku.PmSkuSubsidyMoney } return afsOrder } func UploadExportContent(content []byte, key string) (downloadURL string, err error) { putPolicy := storage.PutPolicy{ Scope: globals.QiniuBucket, Expires: 10 * 60, DeleteAfterDays: 1, } upToken := putPolicy.UploadToken(api.QiniuAPI) cfg := &storage.Config{} formUploader := storage.NewFormUploader(cfg) ret := storage.PutRet{} for i := 0; i < 3; i++ { if err = formUploader.Put(context.Background(), &ret, upToken, key, bytes.NewReader(content), int64(len(content)), &storage.PutExtra{}); err == nil { break } } if err == nil { downloadURL = ComposeQiniuResURL(key) } return downloadURL, err } func UploadExeclAndPushMsg(sheetList []*excel.Obj2ExcelSheetConfig, name string) (downloadURL, fileName string, err error) { excelBin := excel.Obj2Excel(sheetList) timeStr := utils.Int64ToStr(time.Now().Unix()) fileName = name + timeStr + fileExt baseapi.SugarLogger.Debugf("WriteToExcel:save %s success", fileName) downloadURL, err = UploadExportContent(excelBin, fileName) return downloadURL, fileName, err } func TaskResult2Hint(resultList []interface{}) (hint string) { strList := make([]string, len(resultList)) for k, v := range resultList { strList[k] = fmt.Sprint(v) } hint = strings.Join(strList, ",") return hint } // 这个函数用于将两个整数合并为一单一int64,不要用于持久化的场景 func Combine2Int(int1, int2 int) (outInt int64) { return int64(int1)*100000 + int64(int2) } func GetLastTimeFromList(now time.Time, timeList []string) (snapshotAt time.Time) { dateStr := utils.Time2DateStr(now) selectTime := utils.Str2Time(utils.Time2DateStr(now.Add(-24*time.Hour)) + " " + timeList[len(timeList)-1]) for _, v := range timeList { tmpTime := utils.Str2Time(dateStr + " " + v) if tmpTime.Sub(now) > 0 { break } selectTime = tmpTime } return selectTime } func GetNextTimeFromList(now time.Time, timeList []string) (snapshotAt time.Time) { dateStr := utils.Time2DateStr(now) timeListLen := len(timeList) selectTime := utils.Str2Time(utils.Time2DateStr(now.Add(24*time.Hour)) + " " + timeList[0]) for k := range timeList { v := timeList[timeListLen-k-1] tmpTime := utils.Str2Time(dateStr + " " + v) if tmpTime.Sub(now) < 0 { break } selectTime = tmpTime } return selectTime } func OperationTime2StrWithSecond(opTime int16) (str string) { str = fmt.Sprintf("%02d:%02d:00", opTime/100, opTime%100) return str } func OperationTime2Str(opTime int16) (str string) { str = fmt.Sprintf("%02d:%02d", opTime/100, opTime%100) return str } func OperationTime2Str2(openTime, closeTime int16) (str string) { str = fmt.Sprintf("%s-%s", OperationTime2Str(openTime), OperationTime2Str(closeTime)) return str } func OperationTime2HourMinuteFormat(time time.Time) (i int16) { return int16(time.Hour()*100 + time.Minute()) } func WriteFile(fileName string, binData []byte) error { err := ioutil.WriteFile(fileName, binData, 0666) return err } func GuessDataResourceVendor(resourceURL string) (vendorID int) { vendorID = -1 for tmpVendorID, urlList := range resourceTypeMap { for _, v := range urlList { if v != "" && strings.Index(resourceURL, "//"+v) >= 0 { vendorID = tmpVendorID break } } if vendorID >= 0 { break } } return vendorID } func BatchString2Slice(strs ...string) (strList []string) { for _, v := range strs { if v != "" { strList = append(strList, v) } } return strList } func GetShortNameFromURL(strURL string) (shortName string) { index := strings.Index(strURL, "?") if index != -1 { strURL = strURL[:index] } index = strings.LastIndex(strURL, "/") if index != -1 { shortName = strURL[index+1:] } return shortName } // 阶梯计算总量 // stageList是一个二维数组,第一维要求是从大到小排序的,第二维是级别及单位代价 func CalcStageValue(stageList [][]float64, totalVolume float64) (value float64) { for _, v := range stageList { if totalVolume > v[0] { used := math.Ceil(totalVolume - v[0]) value += v[1] * used totalVolume -= used } } return value } func GetOneEmailFromStr(str string) (email string) { if str != "" { searchResult := emailPat.FindStringSubmatch(str) if searchResult != nil && len(searchResult) > 0 { email = searchResult[0] } } return email } // 计算一个坐标点距离一个门店的距离,单位为米,如果不在有效范围内,则返回0 func Point2StoreDistance(lng, lat float64, intStoreLng, intStoreLat int, deliveryRangeType int8, deliveryRange string) (distance int) { // storeLng := IntCoordinate2Standard(intStoreLng) // storeLat := IntCoordinate2Standard(intStoreLat) // if deliveryRangeType == model.DeliveryRangeTypeRadius { // maxDistance := int(utils.Str2Int64WithDefault(deliveryRange, 0)) // distance = int(EarthDistance(lng, lat, storeLng, storeLat) * 1000) // if distance > maxDistance { // distance = 0 // } // } else { // points := CoordinateStr2Points(deliveryRange) // if utils.IsPointInPolygon(lng, lat, points) { // distance = int(EarthDistance(lng, lat, storeLng, storeLat) * 1000) // } // } return distance } func TranslateSoundSize(vendorID, soundPercentage int) (soundSize string) { if vendorID == model.VendorIDYiLianYun || vendorID == model.VendorIDFeiE { if soundPercentage == 0 { soundSize = "0" } if soundPercentage > 0 && soundPercentage <= 33 { soundSize = "1" } if soundPercentage > 33 && soundPercentage <= 66 { soundSize = "2" } if soundPercentage > 66 && soundPercentage <= 100 { soundSize = "3" } } return soundSize } //ECB,AES模式解密 //目前就京东商城订单手机号解密用 func DecryptDESECB(d, key []byte) string { data, err := base64.StdEncoding.DecodeString(string(d)) if err != nil { return "" } block, err := aes.NewCipher(key) if err != nil { return "" } bs := block.BlockSize() if len(data)%bs != 0 { return "" } out := make([]byte, len(data)) dst := out for len(data) > 0 { block.Decrypt(dst, data[:bs]) data = data[bs:] dst = dst[bs:] } out = PKCS5UnPadding(out) return string(out) } func PKCS5UnPadding(origData []byte) []byte { length := len(origData) unpadding := int(origData[length-1]) return origData[:(length - unpadding)] } //合成水印图 func MixWatermarkImg(imgWatermark, img string, exPrefixBegin, exPrefixEnd *time.Time) (imgMix string) { if exPrefixBegin != nil && exPrefixEnd != nil { if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixBegin) >= 0 && utils.Time2Date(time.Now()).Sub(*exPrefixEnd) <= 0 { baseURL := base64.URLEncoding.EncodeToString([]byte(imgWatermark)) var imgUrl string if strings.Contains(img, "?") { imgUrl = img + "/imageView2/0/q/75|watermark/1/image/" + baseURL + "/dissolve/100/gravity/Center/dx/0/dy/0" } else { imgUrl = img + "?imageView2/0/q/75|watermark/1/image/" + baseURL + "/dissolve/100/gravity/Center/dx/0/dy/0" } if resBinary, _, err := DownloadFileByURL(imgUrl); err == nil { if downloadURL, err := UploadExportContent(resBinary, utils.Int64ToStr(time.Now().Unix())+img[strings.LastIndex(img, "/")+1:len(img)]); err == nil { if err == nil { return downloadURL } } } } if utils.Time2Date(time.Now().Add(6*time.Hour)).Sub(*exPrefixEnd) > 0 { return imgMix } } return imgMix } func GetDefendPriceIssue() (issue int) { if time.Now().Hour() >= 22 { issue = utils.Str2Int(time.Now().AddDate(0, 0, 1).Format("20060102")) } else { issue = utils.Str2Int(time.Now().Format("20060102")) } return issue } func GetLastDefendPriceIssue() (issue int) { return utils.Str2Int(time.Now().AddDate(0, 0, 1).Format("20060102")) } //根据一堆坐标求面积 //有待考证,不过暂时拿来用 func ComputeSignedArea(path []string) (s float64) { var ( radius = 6371009 len = len(path) total float64 prev = path[len-1] ) if len < 3 { return } prevTanLat := math.Tan(((math.Pi/2 - utils.Str2Float64(strings.Split(prev, ",")[1])/180*math.Pi) / 2)) prevLng := utils.Str2Float64(strings.Split(prev, ",")[0]) / 180 * math.Pi for i := 0; i < len; i++ { tanLat := math.Tan(((math.Pi/2 - utils.Str2Float64(strings.Split(path[i], ",")[1])/180*math.Pi) / 2)) lng := utils.Str2Float64(strings.Split(path[i], ",")[0]) / 180 * math.Pi total += polarTriangleArea(tanLat, lng, prevTanLat, prevLng) prevTanLat = tanLat prevLng = lng } return math.Abs(total * (float64(radius) * float64(radius))) } func polarTriangleArea(tan1, lng1, tan2, lng2 float64) (s float64) { deltaLng := lng1 - lng2 t := tan1 * tan2 return 2 * math.Atan2(t*math.Sin(deltaLng), 1+t*math.Cos(deltaLng)) } func GenRandomString(l int) string { str := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" bytes := []byte(str) result := []byte{} r := rand.New(rand.NewSource(time.Now().UnixNano())) for i := 0; i < l; i++ { result = append(result, bytes[r.Intn(len(bytes))]) } return string(result) }