package common import ( "base/app/config" "base/app/constant" "bytes" "crypto/md5" "encoding/hex" "errors" "fmt" "git.oa00.com/go/mysql" "git.oa00.com/go/redis" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "github.com/shopspring/decimal" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" "io" "io/ioutil" "log" "math" "math/rand" "net/http" "os" "path/filepath" "regexp" "strconv" "strings" "time" ) // @Title 随机数种子 func init() { // 随机数种子 rand.Seed(time.Now().UnixNano()) } // @Title md5加密 func MD5(str string) string { h := md5.New() h.Write([]byte(str)) return hex.EncodeToString(h.Sum(nil)) } // MD5Byte @Title md5加密 func MD5Byte(str []byte) string { h := md5.New() h.Write(str) return hex.EncodeToString(h.Sum(nil)) } // @Title 生成随机数 func RandStr(n int, str ...string) string { s := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" if len(str) > 0 { s = str[0] } res := "" for i := 0; i < n; i++ { res += string(s[rand.Intn(len(s))]) } return res } // @Title 处理验证错误消息 func GetVerErr(err error) string { er, ok := err.(validator.ValidationErrors) if ok { field := er[0].Field() if field == er[0].StructField() { field = strings.ToLower(field[0:1]) + field[1:] } switch er[0].Tag() { case "required": return field + "不能为空" case "min": if er[0].Type().String() == "string" { return field + "不能小于" + er[0].Param() + "位" } return field + "不能小于" + er[0].Param() } return field + "错误" } else { return "参数格式错误" } } // @Title 是否在数组中 func InArray(need interface{}, data interface{}) bool { if datas, ok := data.([]int); ok { for _, item := range datas { if item == need { return true } } } if datas, ok := data.([]uint); ok { for _, item := range datas { if item == need { return true } } } if datas, ok := data.([]string); ok { for _, item := range datas { if item == need { return true } } } return false } // CreateDateDir 根据当前日期来创建文件夹 func CreateDateDir(Path string) string { folderName := time.Now().Format("20060102") folderPath := filepath.Join(Path, folderName) if _, err := os.Stat(folderPath); os.IsNotExist(err) { os.MkdirAll(folderPath, 0755) } return folderName } // @Title 下载文件 func DownloadFormUrl(src string, filename string) error { res, err := http.Get(src) if err != nil { return err } defer res.Body.Close() // 获得get请求响应的reader对象 body, err := io.ReadAll(res.Body) if err != nil { return err } out, err := os.Create(filename) if err != nil { return err } if _, err := io.Copy(out, bytes.NewReader(body)); err != nil { return err } return nil } // @Title utf8转gbk func Utf8ToGbk(source string) string { result, _, _ := transform.String(simplifiedchinese.GBK.NewEncoder(), source) return result } // @Title gbk转utf8 func GbkToUtf8(source string) string { result, _, _ := transform.String(simplifiedchinese.GBK.NewDecoder(), source) return result } // GetPassword @Title 密码加密 func GetPassword(password, salt string) string { return MD5(salt + MD5(password+salt)) } // GetDeviceType @Title 获取设备类型 func GetDeviceType(c *gin.Context) uint { switch strings.ToLower(c.GetHeader("Device-Type")) { default: return constant.DeviceTypeWeb } } // FindParents @Title 查询所有上级 func FindParents(tableName, id, parentId string, findId uint, result interface{}) { mysql.Db.Raw(fmt.Sprintf(`SELECT T2.* FROM ( SELECT @r AS _id, (SELECT @r := %s FROM %s WHERE %s = _id) FROM (SELECT @r := ?) vars, %s h WHERE @r <> 0) T1 JOIN %s T2 ON T1._id = T2.%s`, parentId, tableName, id, tableName, tableName, id), findId).Scan(result) return } // GenNo @Title 生成编号 func GenNo(NoPrefix string) (string, error) { date := time.Now().Format("20060102") redisKey := fmt.Sprintf("gen:%s:%s", NoPrefix, date) result, err := redis.Redis.Incr(redisKey).Result() if err != nil { return "", errors.New("生成失败") } redis.Redis.Expire(redisKey, time.Hour*24) if result > 9999 { return "", errors.New("生成失败") } if !config.IsProd() { date += "test" } return fmt.Sprintf("%s%s%.4d", NoPrefix, date, result), nil } // GenNo6 @Title 生成六位编号 func GenNo6(number uint) (result string, err error) { s := "000000" sn := strconv.Itoa(int(number)) if len(sn) > 6 { return result, errors.New("车辆编号溢出六位限制") } result = s[0:(len(s)-len(sn))] + sn return } // GetRequestBody @Title 获取请求数据 func GetRequestBody(request *http.Request) ([]byte, error) { body, err := ioutil.ReadAll(request.Body) if err != nil { return nil, fmt.Errorf("read request body err: %v", err) } _ = request.Body.Close() request.Body = ioutil.NopCloser(bytes.NewBuffer(body)) return body, nil } // Ternary @Title 三元运算 func Ternary(condition bool, resultA, resultB interface{}) interface{} { if condition { return resultA } return resultB } func UintTernary(condition bool, resultA, resultB uint) uint { if condition { return resultA } return resultB } func StringTernary(condition bool, resultA, resultB string) string { if condition { return resultA } return resultB } // IdCardRegexp @Title 身份证验证 func IdCardRegexp(idCard string) bool { rgx := "^[1-9]\\d{5}(18|19|([23]\\d))\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$" //身份证号码: 空格也需要表示出来, 直接打空格是不起作用的 \s表示空字符 [\s]任意空字符 ?出现0次或者次 //([1-6]\d{5})(19\d{2}|20\d{2})(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])(\d{3}[\dxX]) // ([1-6]\d{5}) 为一组 第一位表示地区 例如 华中 华南等 数字为1-6 [1-6]表示任意一个 \d{5} 数字共5位 //(19\d{2}|20\d{2}) 为一组 年的前两位要么为19 要么为20 后两位为\d{2}数字出现两次 //(0[1-9]|1[012]) 为一组 月第一位为0或者为1 为0的时候 后边为[1-9]任意一个数字 为1的时候 后边为[012]任意一个数字 //(0[1-9]|[12]\d|3[01]) 为一组 日第一位要么为0要么为1或者2或者3 为0的时候第2位[1-9]任意一个数字 第1位为1或者2的时候 第2位为\d任意一个数字相当于[0-9] reg := regexp.MustCompile(rgx) result := reg.MatchString(idCard) return result } // 人民币大写 func ConvertDecimalToCny(num decimal.Decimal) string { f, _ := num.Float64() return ConvertNumToCny(f) } // 人民币大写 func ConvertNumToCny(num float64) string { strnum := strconv.FormatFloat(num*100, 'f', 0, 64) if strnum == "0" { return "零" } sliceUnit := []string{"仟", "佰", "拾", "亿", "仟", "佰", "拾", "万", "仟", "佰", "拾", "元", "角", "分"} // log.Println(sliceUnit[:len(sliceUnit)-2]) s := sliceUnit[len(sliceUnit)-len(strnum) : len(sliceUnit)] upperDigitUnit := map[string]string{"0": "零", "1": "壹", "2": "贰", "3": "叁", "4": "肆", "5": "伍", "6": "陆", "7": "柒", "8": "捌", "9": "玖"} str := "" for k, v := range strnum[:] { str = str + upperDigitUnit[string(v)] + s[k] } reg, err := regexp.Compile(`零角零分$`) str = reg.ReplaceAllString(str, "整") reg, err = regexp.Compile(`零角`) str = reg.ReplaceAllString(str, "零") reg, err = regexp.Compile(`零分$`) str = reg.ReplaceAllString(str, "整") reg, err = regexp.Compile(`零[仟佰拾]`) str = reg.ReplaceAllString(str, "零") reg, err = regexp.Compile(`零{2,}`) str = reg.ReplaceAllString(str, "零") reg, err = regexp.Compile(`零亿`) str = reg.ReplaceAllString(str, "亿") reg, err = regexp.Compile(`零万`) str = reg.ReplaceAllString(str, "万") reg, err = regexp.Compile(`零*元`) str = reg.ReplaceAllString(str, "元") reg, err = regexp.Compile(`亿零{0, 3}万`) str = reg.ReplaceAllString(str, "^元") reg, err = regexp.Compile(`零元`) str = reg.ReplaceAllString(str, "零") if err != nil { log.Fatal(err) } return str } // 截取字符串 func SliceStr(str string, index int) string { if math.Abs(float64(index)) > float64(len(str)) { return str } if index < 0 { return string([]rune(str)[len([]rune(str))+index:]) } return string([]rune(str)[:index]) } // TimeFormat func TimeFormat(time time.Time, format string) string { if time.IsZero() { return "/" } return time.Format(format) } // //// Thumb 生成缩略图 //func Thumb(url string, w, h float64) { // filename := filepath.Join(config.Config.Upload.Root, url) // saveName := filepath.Join(config.Config.Upload.Thumb, url) // if FileExists(saveName) { // //c.File(saveName) // return // } // // //创建新的MagicWand // mw := imagick.NewMagickWand() // //读取文件 // err := mw.ReadImage(filename) // if err != nil { // return // } // // if w != 0 || h != 0 { // err := reset(w, h, mw) // if err != nil { // //c.File(filename) // return // } // } // // //改变图片质量 // err = mw.SetImageCompressionQuality(85) // if err != nil { // return // } // //导出图片 // if err := os.MkdirAll(filepath.Dir(saveName), os.ModePerm); err != nil { // return // } // err = mw.WriteImage(saveName) // //c.File(saveName) //} // //func FileExists(name string) bool { // if _, err := os.Stat(name); err != nil { // if os.IsNotExist(err) { // return false // } // } // return true //} // //func reset(w float64, h float64, mw *imagick.MagickWand) error { // width := float64(mw.GetImageWidth()) // height := float64(mw.GetImageHeight()) // if w >= width || h >= height { // return errors.New("can't max") // } // var newH, newW, crop_x, crop_y float64 // if w == 0 { // newH = h // newW = width / (height / h) // } else if h == 0 { // newW = w // newH = height / (width / w) // } else { // if width/w < height/h { // newW = w // newH = height / (width / w) // crop_x = 0 // crop_y = (newH - h) / 2 // } else { // newH = h // newW = width / (height / h) // crop_x = (newW - w) / 2 // crop_y = 0 // } // } // _ = mw.ResizeImage(uint(newW), uint(newH), imagick.FILTER_LANCZOS) // if w != 0 && h != 0 { // _ = mw.CropImage(uint(w), uint(h), int(crop_x), int(crop_y)) // } // return nil //} //