123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571 |
- /*
- * @description: 常用函数
- * @Author: CP
- * @Date: 2020-08-21 11:12:56
- * @FilePath: \construction_management\comm\functions.go
- */
- package comm
- import (
- "bytes"
- "crypto/aes"
- "crypto/cipher"
- "encoding/base64"
- "errors"
- "math"
- "math/rand"
- "time"
- "unicode"
- "crypto/md5"
- "encoding/binary"
- "fmt"
- "strconv"
- "strings"
- "go.mod/conf"
- "go.mod/models"
- "go.mod/web/viewmodels"
- )
- // 账号-构造视图层models
- func MakeProjectAccountVM(modelsAccount *models.CmProjectAccount) viewmodels.ProjectAccount {
- viewAccountData := viewmodels.ProjectAccount{}
- aesId, _ := AesEncrypt(strconv.Itoa(modelsAccount.Id), conf.SignSecret)
- aesProjectId, _ := AesEncrypt(strconv.Itoa(modelsAccount.ProjectId), conf.SignSecret)
- viewAccountData.Id = aesId
- viewAccountData.ProjectId = aesProjectId
- viewAccountData.Account = modelsAccount.Account
- viewAccountData.Name = modelsAccount.Name
- viewAccountData.Company = modelsAccount.Company
- viewAccountData.Role = modelsAccount.Role
- viewAccountData.Mobile = modelsAccount.Mobile
- viewAccountData.Telephone = modelsAccount.Telephone
- viewAccountData.IsAdmin = modelsAccount.IsAdmin
- viewAccountData.AccountGroup = modelsAccount.AccountGroup
- viewAccountData.Enable = modelsAccount.Enable
- viewAccountData.Position = modelsAccount.Position
- // viewAccountData.ContractPermission = modelsAccount.ContractPermission
- // viewAccountData.QualityPermission = modelsAccount.QualityPermission
- // viewAccountData.SafePermission = modelsAccount.SafePermission
- return viewAccountData
- }
- // 创建合同目录树
- func MakeFolderContract(Data []*viewmodels.FolderContract, node *viewmodels.FolderContract) { //参数为父节点,添加父节点的子节点指针切片
- childs, _ := HaveChildContract(Data, node) //判断节点是否有子节点并返回
- if childs != nil {
- // 子节点总数
- Total := len(childs)
- node.ChildsTotal = Total
- // 标记最后一个元素
- end := Total - 1
- childs[end].IsEnd = true
- // 往父节点添加子节点
- node.Children = append(node.Children, childs[0:]...) //添加子节点
- // 1.标段汇总
- // 1-1.合同相关汇总-收入金额
- totalIncome := 0.00
- // 1-2.合同总数
- totalContractNumber := 0
- // 1-3.汇款进度
- totalReturn := 0.00
- // 1-4支出金额
- totalPay := 0.00
- totalPaid := 0.00
- // 1-5 安全巡检
- safeTotal := 0
- safeTotalRectification := 0
- safeTotalRectificationIn := 0
- // 1-6 质量巡检
- qualityTotal := 0
- qualityTotalRectification := 0
- qualityTotalRectificationIn := 0
- for _, v := range childs { //查询子节点的子节点,并添加到子节点
- _, has := HaveChildContract(Data, v)
- if has {
- // 递归添加节点
- MakeFolderContract(Data, v)
- }
- // 目录下是否包含标段
- if v.Isfolder == 0 {
- node.IsBid = true
- } else {
- node.HasFolder = true
- }
- // 2.标段汇总
- // 2-1收入金额 合计
- price, _ := strconv.ParseFloat(v.ContractsIncome, 64)
- totalIncome = totalIncome + price
- // 2-2合同总数 合计
- totalContractNumber = totalContractNumber + v.Contracts
- // 2-3 汇款进度
- price, _ = strconv.ParseFloat(v.ContractsReturned, 64)
- totalReturn = totalReturn + price
- //
- price, _ = strconv.ParseFloat(v.ContractsPay, 64)
- totalPay = totalPay + price
- price, _ = strconv.ParseFloat(v.ContractsPaid, 64)
- totalPaid = totalPaid + price
- // 安全巡检
- safeTotal = safeTotal + v.SafeTotal
- safeTotalRectification = safeTotalRectification + v.SafeRectification
- safeTotalRectificationIn = safeTotalRectificationIn + v.SafeRectificationIn
- // 1-6 质量巡检
- qualityTotal = safeTotal + v.QualityTotal
- qualityTotalRectification = safeTotalRectification + v.QualityRectification
- qualityTotalRectificationIn = safeTotalRectificationIn + v.QualityRectificationIn
- }
- node.ContractsIncome = fmt.Sprintf("%.2f", totalIncome)
- node.Contracts = totalContractNumber
- // 汇款进度
- quotient := totalReturn / totalIncome
- if math.IsNaN(quotient) {
- quotient = 0
- }
- node.ContractsIncomeProgress = fmt.Sprintf("%.0f", (quotient)*100) + "%"
- // 支出相关
- node.ContractsPay = fmt.Sprintf("%.2f", totalPay)
- quotient = totalPaid / totalPay
- if math.IsNaN(quotient) {
- quotient = 0
- }
- node.ContractsPayProgress = fmt.Sprintf("%.0f", (quotient)*100) + "%"
- // 安全巡检
- node.SafeTotal = safeTotal
- node.SafeRectification = safeTotalRectification
- node.SafeRectificationIn = safeTotalRectificationIn
- // 质量巡检
- node.QualityTotal = qualityTotal
- node.QualityRectification = qualityTotalRectification
- node.QualityRectificationIn = qualityTotalRectificationIn
- }
- }
- // 是否有子树
- func HaveChildContract(Data []*viewmodels.FolderContract, node *viewmodels.FolderContract) (child []*viewmodels.FolderContract, yes bool) {
- for _, v := range Data {
- if v.ParentId == node.Id {
- child = append(child, v)
- }
- }
- if child != nil {
- yes = true
- }
- return
- }
- // 创建合同项目节树
- func MakeSectionContract(Data []*viewmodels.TreeSectionContract, node *viewmodels.TreeSectionContract) { //参数为父节点,添加父节点的子节点指针切片
- childs, _ := haveChildSectionContract(Data, node) //判断节点是否有子节点并返回
- if childs != nil {
- // 往父节点添加子节点
- // 孩子们从小到大排序
- if len(childs) != 0 {
- sectionSelectionSort(childs)
- childs[0].ElderBrother = false
- childs[len(childs)-1].IsEnd = true
- }
- // 项目节父项使用
- // 1.合同总金额 回款总金额 已支付总金额
- // contractPriceTotal := 0.00
- // returnPriceTotal := 0.00
- // paidPriceTotal := 0.00
- node.Children = append(node.Children, childs[0:]...) //添加子节点
- for _, v := range childs { //查询子节点的子节点,并添加到子节点
- _, has := haveChildSectionContract(Data, v)
- if has {
- // 递归添加节点
- MakeSectionContract(Data, v)
- }
- // 2.计算父项中金额
- // contractPrice, _ := strconv.ParseFloat(v.ContractPrice, 64)
- // contractPriceTotal += contractPrice
- // returnPrice, _ := strconv.ParseFloat(v.ContractReturned, 64)
- // returnPriceTotal += returnPrice
- // paidPrice, _ := strconv.ParseFloat(v.ContractsPaid, 64)
- // paidPriceTotal += paidPrice
- }
- // 3.赋值到父项中
- // node.ContractPrice = fmt.Sprintf("%.2f", contractPriceTotal)
- // node.ContractReturned = fmt.Sprintf("%.2f", returnPriceTotal)
- // node.ContractsPaid = fmt.Sprintf("%.2f", paidPriceTotal)
- }
- }
- // 合同项目节孩子排序
- func sectionSelectionSort(child []*viewmodels.TreeSectionContract) {
- for i := 0; i < len(child); i++ {
- minIndex := i
- // 查找最小值
- for j := i; j < len(child); j++ {
- if child[j].Serial < child[minIndex].Serial {
- minIndex = j
- }
- }
- swapContract(child, i, minIndex)
- }
- }
- func swapContract(child []*viewmodels.TreeSectionContract, i int, minIndex int) {
- t := child[i]
- child[i] = child[minIndex]
- child[minIndex] = t
- }
- // 是否有子树
- func haveChildSectionContract(Data []*viewmodels.TreeSectionContract, node *viewmodels.TreeSectionContract) (child []*viewmodels.TreeSectionContract, yes bool) {
- for _, v := range Data {
- if v.ParentId == node.Id {
- child = append(child, v)
- }
- }
- if child != nil {
- yes = true
- }
- return
- }
- // 当前时间的时间戳
- func NowUnix() int {
- return int(time.Now().In(conf.SysTimeLocation).Unix())
- }
- // 将unix时间戳格式化为yyyymmdd H:i:s格式字符串
- func FormatFromUnixTime(t int64) string {
- if t > 0 {
- return time.Unix(t, 0).Format(conf.SysTimeform)
- } else {
- return time.Now().Format(conf.SysTimeform)
- }
- }
- // 将unix时间戳格式化为yyyymmdd格式字符串
- func FormatFromUnixTimeShort(t int64) string {
- if t > 0 {
- return time.Unix(t, 0).Format(conf.SysTimeformShort)
- } else {
- return time.Now().Format(conf.SysTimeformShort)
- }
- }
- // 将字符串转成时间
- func ParseTime(str string) (time.Time, error) {
- return time.ParseInLocation(conf.SysTimeform, str, conf.SysTimeLocation)
- }
- // 得到一个随机数
- func Random(max int) int {
- r := rand.New(rand.NewSource(time.Now().UnixNano()))
- if max < 1 {
- return r.Int()
- } else {
- return r.Intn(max)
- }
- }
- // 加密密码
- func CreatePasswordSign(password string, account string) string {
- str := string(conf.SignSecret) + password + account
- str1 := fmt.Sprintf("%x", md5.Sum([]byte(str)))
- sign := fmt.Sprintf("%x", md5.Sum([]byte(str1)))
- return sign
- }
- // 对字符串进行签名
- func CreateSign(str string) string {
- str = string(conf.SignSecret) + str
- str1 := fmt.Sprintf("%x", md5.Sum([]byte(str)))
- sign := fmt.Sprintf("%x", md5.Sum([]byte(str1)))
- return sign
- }
- // 对一个字符串进行加密
- func Encrypt(key, text []byte) (string, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return "", err
- }
- b := base64.StdEncoding.EncodeToString(text)
- ciphertext := make([]byte, aes.BlockSize+len(b))
- iv := ciphertext[:aes.BlockSize]
- //if _, err := io.ReadFull(rand.Reader, iv); err != nil {
- // return nil, err
- //}
- cfb := cipher.NewCFBEncrypter(block, iv)
- cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
- return base64.RawURLEncoding.EncodeToString(ciphertext), nil
- }
- // 对一个字符串进行解密
- func Decrypt(key, text []byte) ([]byte, error) {
- block, err := aes.NewCipher(key)
- if err != nil {
- return nil, err
- }
- if len(text) < aes.BlockSize {
- return nil, errors.New("ciphertext too short")
- }
- iv := text[:aes.BlockSize]
- text = text[aes.BlockSize:]
- cfb := cipher.NewCFBDecrypter(block, iv)
- cfb.XORKeyStream(text, text)
- data, err := base64.StdEncoding.DecodeString(string(text))
- if err != nil {
- return nil, err
- }
- return data, nil
- }
- // 加密
- func AesEncrypt(orig string, key string) (string, error) {
- // 转成字节数组
- origData := []byte(orig)
- k := []byte(key)
- // 分组秘钥
- block, err := aes.NewCipher(k)
- if err != nil {
- return "", err
- }
- // 获取秘钥块的长度
- blockSize := block.BlockSize()
- // 补全码
- origData = PKCS7Padding(origData, blockSize)
- // 加密模式
- blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
- // 创建数组
- cryted := make([]byte, len(origData))
- // 加密
- blockMode.CryptBlocks(cryted, origData)
- //使用RawURLEncoding 不要使用StdEncoding
- //不要使用StdEncoding 放在url参数中回导致错误
- return base64.RawURLEncoding.EncodeToString(cryted), nil
- }
- // 解密
- func AesDecrypt(cryted string, key string) (string, error) {
- //使用RawURLEncoding 不要使用StdEncoding
- //不要使用StdEncoding 放在url参数中回导致错误
- crytedByte, err := base64.RawURLEncoding.DecodeString(cryted)
- if err != nil {
- return "", err
- }
- k := []byte(key)
- // 分组秘钥
- block, err := aes.NewCipher(k)
- if err != nil {
- return "", err
- }
- // 获取秘钥块的长度
- blockSize := block.BlockSize()
- // 加密模式
- blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
- // 创建数组
- orig := make([]byte, len(crytedByte))
- // 解密--传入不正确的字符时会报错-TODO 需捕获
- blockMode.CryptBlocks(orig, crytedByte)
- // 去补全码
- orig = PKCS7UnPadding(orig)
- return string(orig), nil
- }
- //补码
- func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
- padding := blocksize - len(ciphertext)%blocksize
- padtext := bytes.Repeat([]byte{byte(padding)}, padding)
- return append(ciphertext, padtext...)
- }
- //去码
- func PKCS7UnPadding(origData []byte) []byte {
- length := len(origData)
- unpadding := int(origData[length-1])
- return origData[:(length - unpadding)]
- }
- // addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
- // 预定义字符是:
- // 单引号(')
- // 双引号(")
- // 反斜杠(\)
- func Addslashes(str string) string {
- tmpRune := []rune{}
- strRune := []rune(str)
- for _, ch := range strRune {
- switch ch {
- case []rune{'\\'}[0], []rune{'"'}[0], []rune{'\''}[0]:
- tmpRune = append(tmpRune, []rune{'\\'}[0])
- tmpRune = append(tmpRune, ch)
- default:
- tmpRune = append(tmpRune, ch)
- }
- }
- return string(tmpRune)
- }
- // stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
- func Stripslashes(str string) string {
- dstRune := []rune{}
- strRune := []rune(str)
- strLenth := len(strRune)
- for i := 0; i < strLenth; i++ {
- if strRune[i] == []rune{'\\'}[0] {
- i++
- }
- dstRune = append(dstRune, strRune[i])
- }
- return string(dstRune)
- }
- // 将字符串的IP转化为数字
- func Ip4toInt(ip string) int64 {
- bits := strings.Split(ip, ".")
- if len(bits) == 4 {
- b0, _ := strconv.Atoi(bits[0])
- b1, _ := strconv.Atoi(bits[1])
- b2, _ := strconv.Atoi(bits[2])
- b3, _ := strconv.Atoi(bits[3])
- var sum int64
- sum += int64(b0) << 24
- sum += int64(b1) << 16
- sum += int64(b2) << 8
- sum += int64(b3)
- return sum
- } else {
- return 0
- }
- }
- // 得到当前时间到下一天零点的延时
- func NextDayDuration() time.Duration {
- year, month, day := time.Now().Add(time.Hour * 24).Date()
- next := time.Date(year, month, day, 0, 0, 0, 0, conf.SysTimeLocation)
- return next.Sub(time.Now())
- }
- // 从接口类型安全获取到int64
- func GetInt64(i interface{}, d int64) int64 {
- if i == nil {
- return d
- }
- switch i.(type) {
- case string:
- num, err := strconv.Atoi(i.(string))
- if err != nil {
- return d
- } else {
- return int64(num)
- }
- case []byte:
- bits := i.([]byte)
- if len(bits) == 8 {
- return int64(binary.LittleEndian.Uint64(bits))
- } else if len(bits) <= 4 {
- num, err := strconv.Atoi(string(bits))
- if err != nil {
- return d
- } else {
- return int64(num)
- }
- }
- case uint:
- return int64(i.(uint))
- case uint8:
- return int64(i.(uint8))
- case uint16:
- return int64(i.(uint16))
- case uint32:
- return int64(i.(uint32))
- case uint64:
- return int64(i.(uint64))
- case int:
- return int64(i.(int))
- case int8:
- return int64(i.(int8))
- case int16:
- return int64(i.(int16))
- case int32:
- return int64(i.(int32))
- case int64:
- return i.(int64)
- case float32:
- return int64(i.(float32))
- case float64:
- return int64(i.(float64))
- }
- return d
- }
- // 从接口类型安全获取到字符串类型
- func GetString(str interface{}, d string) string {
- if str == nil {
- return d
- }
- switch str.(type) {
- case string:
- return str.(string)
- case []byte:
- return string(str.([]byte))
- }
- return fmt.Sprintf("%s", str)
- }
- // 从map中得到指定的key
- func GetInt64FromMap(dm map[string]interface{}, key string, dft int64) int64 {
- data, ok := dm[key]
- if !ok {
- return dft
- }
- return GetInt64(data, dft)
- }
- // 从map中得到指定的key
- func GetInt64FromStringMap(dm map[string]string, key string, dft int64) int64 {
- data, ok := dm[key]
- if !ok {
- return dft
- }
- return GetInt64(data, dft)
- }
- // 从map中得到指定的key
- func GetStringFromMap(dm map[string]interface{}, key string, dft string) string {
- data, ok := dm[key]
- if !ok {
- return dft
- }
- return GetString(data, dft)
- }
- // 从map中得到指定的key
- func GetStringFromStringMap(dm map[string]string, key string, dft string) string {
- data, ok := dm[key]
- if !ok {
- return dft
- }
- return data
- }
- // 首字母大写
- func Ucfirst(str string) string {
- for i, v := range str {
- return string(unicode.ToUpper(v)) + str[i+1:]
- }
- return ""
- }
|