Files
jx-callback/business/jxutils/jxutils.go
2021-04-20 16:48:56 +08:00

911 lines
27 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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",
},
}
)
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("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, positon string) (imgMix string) {
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/" + positon + "/dx/0/dy/0"
} else {
imgUrl = img + "?imageView2/0/q/75|watermark/1/image/" + baseURL + "/dissolve/100/gravity/" + positon + "/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
}
}
}
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)
}
func GetDayTime() (dayTimeBegin, dayTimeEnd time.Time) {
dayTimeBegin = utils.Str2Time(utils.Time2Str(utils.Time2Date(time.Now())) + " 00:00:00")
dayTimeEnd = dayTimeBegin.AddDate(0, 0, 1)
return dayTimeBegin, dayTimeEnd
}
func GetWeekTime() (weekTimeBegin, weekTimeEnd time.Time) {
offset := int(time.Now().Weekday() - 1)
if offset == -1 {
offset = -6
}
weekTimeBegin = time.Now().AddDate(0, 0, offset)
weekTimeEnd = weekTimeBegin.AddDate(0, 0, 7)
return weekTimeBegin, weekTimeEnd
}