You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

421 lines
10 KiB

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
//}
//