functions.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /*
  2. * @description: 常用函数
  3. * @Author: CP
  4. * @Date: 2020-08-21 11:12:56
  5. * @FilePath: \construction_management\comm\functions.go
  6. */
  7. package comm
  8. import (
  9. "bytes"
  10. "crypto/aes"
  11. "crypto/cipher"
  12. "encoding/base64"
  13. "errors"
  14. "math/rand"
  15. "time"
  16. "unicode"
  17. "crypto/md5"
  18. "encoding/binary"
  19. "fmt"
  20. "strconv"
  21. "strings"
  22. "go.mod/conf"
  23. "go.mod/models"
  24. "go.mod/web/viewmodels"
  25. )
  26. // 账号-构造视图层models
  27. func MakeProjectAccountVM(modelsAccount *models.CmProjectAccount) viewmodels.ProjectAccount {
  28. viewAccountData := viewmodels.ProjectAccount{}
  29. aesId, _ := AesEncrypt(strconv.Itoa(modelsAccount.Id), conf.SignSecret)
  30. aesProjectId, _ := AesEncrypt(strconv.Itoa(modelsAccount.ProjectId), conf.SignSecret)
  31. viewAccountData.Id = aesId
  32. viewAccountData.ProjectId = aesProjectId
  33. viewAccountData.Account = modelsAccount.Account
  34. viewAccountData.Name = modelsAccount.Name
  35. viewAccountData.Company = modelsAccount.Company
  36. viewAccountData.Role = modelsAccount.Role
  37. viewAccountData.Mobile = modelsAccount.Mobile
  38. viewAccountData.Telephone = modelsAccount.Telephone
  39. viewAccountData.IsAdmin = modelsAccount.IsAdmin
  40. viewAccountData.AccountGroup = modelsAccount.AccountGroup
  41. viewAccountData.Enable = modelsAccount.Enable
  42. viewAccountData.Position = modelsAccount.Position
  43. return viewAccountData
  44. }
  45. // 创建合同目录树
  46. func MakeFolderContract(Data []*viewmodels.FolderContract, node *viewmodels.FolderContract) { //参数为父节点,添加父节点的子节点指针切片
  47. childs, _ := HaveChildContract(Data, node) //判断节点是否有子节点并返回
  48. if childs != nil {
  49. // 子节点总数
  50. Total := len(childs)
  51. node.ChildsTotal = Total
  52. // 标记最后一个元素
  53. end := Total - 1
  54. childs[end].IsEnd = true
  55. // 往父节点添加子节点
  56. node.Children = append(node.Children, childs[0:]...) //添加子节点
  57. for _, v := range childs { //查询子节点的子节点,并添加到子节点
  58. _, has := HaveChildContract(Data, v)
  59. if has {
  60. // 递归添加节点
  61. MakeFolderContract(Data, v)
  62. }
  63. // 目录下是否包含标段
  64. if v.Isfolder == 0 {
  65. node.IsBid = true
  66. } else {
  67. node.HasFolder = true
  68. }
  69. }
  70. }
  71. }
  72. // 是否有子树
  73. func HaveChildContract(Data []*viewmodels.FolderContract, node *viewmodels.FolderContract) (child []*viewmodels.FolderContract, yes bool) {
  74. for _, v := range Data {
  75. if v.ParentId == node.Id {
  76. child = append(child, v)
  77. }
  78. }
  79. if child != nil {
  80. yes = true
  81. }
  82. return
  83. }
  84. // 创建合同项目节树
  85. func MakeSectionContract(Data []*viewmodels.TreeSectionContract, node *viewmodels.TreeSectionContract) { //参数为父节点,添加父节点的子节点指针切片
  86. childs, _ := haveChildSectionContract(Data, node) //判断节点是否有子节点并返回
  87. if childs != nil {
  88. // 往父节点添加子节点
  89. // 孩子们从小到大排序
  90. if len(childs) != 0 {
  91. sectionSelectionSort(childs)
  92. childs[0].ElderBrother = false
  93. childs[len(childs)-1].IsEnd = true
  94. }
  95. node.Children = append(node.Children, childs[0:]...) //添加子节点
  96. for _, v := range childs { //查询子节点的子节点,并添加到子节点
  97. _, has := haveChildSectionContract(Data, v)
  98. if has {
  99. // 递归添加节点
  100. MakeSectionContract(Data, v)
  101. }
  102. }
  103. }
  104. }
  105. // 合同项目节孩子排序
  106. func sectionSelectionSort(child []*viewmodels.TreeSectionContract) {
  107. for i := 0; i < len(child); i++ {
  108. minIndex := i
  109. // 查找最小值
  110. for j := i; j < len(child); j++ {
  111. if child[j].Serial < child[minIndex].Serial {
  112. minIndex = j
  113. }
  114. }
  115. swapContract(child, i, minIndex)
  116. }
  117. }
  118. func swapContract(child []*viewmodels.TreeSectionContract, i int, minIndex int) {
  119. t := child[i]
  120. child[i] = child[minIndex]
  121. child[minIndex] = t
  122. }
  123. // 是否有子树
  124. func haveChildSectionContract(Data []*viewmodels.TreeSectionContract, node *viewmodels.TreeSectionContract) (child []*viewmodels.TreeSectionContract, yes bool) {
  125. for _, v := range Data {
  126. if v.ParentId == node.Id {
  127. child = append(child, v)
  128. }
  129. }
  130. if child != nil {
  131. yes = true
  132. }
  133. return
  134. }
  135. // 当前时间的时间戳
  136. func NowUnix() int {
  137. return int(time.Now().In(conf.SysTimeLocation).Unix())
  138. }
  139. // 将unix时间戳格式化为yyyymmdd H:i:s格式字符串
  140. func FormatFromUnixTime(t int64) string {
  141. if t > 0 {
  142. return time.Unix(t, 0).Format(conf.SysTimeform)
  143. } else {
  144. return time.Now().Format(conf.SysTimeform)
  145. }
  146. }
  147. // 将unix时间戳格式化为yyyymmdd格式字符串
  148. func FormatFromUnixTimeShort(t int64) string {
  149. if t > 0 {
  150. return time.Unix(t, 0).Format(conf.SysTimeformShort)
  151. } else {
  152. return time.Now().Format(conf.SysTimeformShort)
  153. }
  154. }
  155. // 将字符串转成时间
  156. func ParseTime(str string) (time.Time, error) {
  157. return time.ParseInLocation(conf.SysTimeform, str, conf.SysTimeLocation)
  158. }
  159. // 得到一个随机数
  160. func Random(max int) int {
  161. r := rand.New(rand.NewSource(time.Now().UnixNano()))
  162. if max < 1 {
  163. return r.Int()
  164. } else {
  165. return r.Intn(max)
  166. }
  167. }
  168. // 加密密码
  169. func CreatePasswordSign(password string, account string) string {
  170. str := string(conf.SignSecret) + password + account
  171. str1 := fmt.Sprintf("%x", md5.Sum([]byte(str)))
  172. sign := fmt.Sprintf("%x", md5.Sum([]byte(str1)))
  173. return sign
  174. }
  175. // 对字符串进行签名
  176. func CreateSign(str string) string {
  177. str = string(conf.SignSecret) + str
  178. str1 := fmt.Sprintf("%x", md5.Sum([]byte(str)))
  179. sign := fmt.Sprintf("%x", md5.Sum([]byte(str1)))
  180. return sign
  181. }
  182. // 对一个字符串进行加密
  183. func Encrypt(key, text []byte) (string, error) {
  184. block, err := aes.NewCipher(key)
  185. if err != nil {
  186. return "", err
  187. }
  188. b := base64.StdEncoding.EncodeToString(text)
  189. ciphertext := make([]byte, aes.BlockSize+len(b))
  190. iv := ciphertext[:aes.BlockSize]
  191. //if _, err := io.ReadFull(rand.Reader, iv); err != nil {
  192. // return nil, err
  193. //}
  194. cfb := cipher.NewCFBEncrypter(block, iv)
  195. cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
  196. return base64.RawURLEncoding.EncodeToString(ciphertext), nil
  197. }
  198. // 对一个字符串进行解密
  199. func Decrypt(key, text []byte) ([]byte, error) {
  200. block, err := aes.NewCipher(key)
  201. if err != nil {
  202. return nil, err
  203. }
  204. if len(text) < aes.BlockSize {
  205. return nil, errors.New("ciphertext too short")
  206. }
  207. iv := text[:aes.BlockSize]
  208. text = text[aes.BlockSize:]
  209. cfb := cipher.NewCFBDecrypter(block, iv)
  210. cfb.XORKeyStream(text, text)
  211. data, err := base64.StdEncoding.DecodeString(string(text))
  212. if err != nil {
  213. return nil, err
  214. }
  215. return data, nil
  216. }
  217. // 加密
  218. func AesEncrypt(orig string, key string) (string, error) {
  219. // 转成字节数组
  220. origData := []byte(orig)
  221. k := []byte(key)
  222. // 分组秘钥
  223. block, err := aes.NewCipher(k)
  224. if err != nil {
  225. return "", err
  226. }
  227. // 获取秘钥块的长度
  228. blockSize := block.BlockSize()
  229. // 补全码
  230. origData = PKCS7Padding(origData, blockSize)
  231. // 加密模式
  232. blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
  233. // 创建数组
  234. cryted := make([]byte, len(origData))
  235. // 加密
  236. blockMode.CryptBlocks(cryted, origData)
  237. //使用RawURLEncoding 不要使用StdEncoding
  238. //不要使用StdEncoding 放在url参数中回导致错误
  239. return base64.RawURLEncoding.EncodeToString(cryted), nil
  240. }
  241. // 解密
  242. func AesDecrypt(cryted string, key string) (string, error) {
  243. //使用RawURLEncoding 不要使用StdEncoding
  244. //不要使用StdEncoding 放在url参数中回导致错误
  245. crytedByte, err := base64.RawURLEncoding.DecodeString(cryted)
  246. if err != nil {
  247. return "", err
  248. }
  249. k := []byte(key)
  250. // 分组秘钥
  251. block, err := aes.NewCipher(k)
  252. if err != nil {
  253. return "", err
  254. }
  255. // 获取秘钥块的长度
  256. blockSize := block.BlockSize()
  257. // 加密模式
  258. blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
  259. // 创建数组
  260. orig := make([]byte, len(crytedByte))
  261. // 解密--传入不正确的字符时会报错-TODO 需捕获
  262. blockMode.CryptBlocks(orig, crytedByte)
  263. // 去补全码
  264. orig = PKCS7UnPadding(orig)
  265. return string(orig), nil
  266. }
  267. //补码
  268. func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
  269. padding := blocksize - len(ciphertext)%blocksize
  270. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  271. return append(ciphertext, padtext...)
  272. }
  273. //去码
  274. func PKCS7UnPadding(origData []byte) []byte {
  275. length := len(origData)
  276. unpadding := int(origData[length-1])
  277. return origData[:(length - unpadding)]
  278. }
  279. // addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
  280. // 预定义字符是:
  281. // 单引号(')
  282. // 双引号(")
  283. // 反斜杠(\)
  284. func Addslashes(str string) string {
  285. tmpRune := []rune{}
  286. strRune := []rune(str)
  287. for _, ch := range strRune {
  288. switch ch {
  289. case []rune{'\\'}[0], []rune{'"'}[0], []rune{'\''}[0]:
  290. tmpRune = append(tmpRune, []rune{'\\'}[0])
  291. tmpRune = append(tmpRune, ch)
  292. default:
  293. tmpRune = append(tmpRune, ch)
  294. }
  295. }
  296. return string(tmpRune)
  297. }
  298. // stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
  299. func Stripslashes(str string) string {
  300. dstRune := []rune{}
  301. strRune := []rune(str)
  302. strLenth := len(strRune)
  303. for i := 0; i < strLenth; i++ {
  304. if strRune[i] == []rune{'\\'}[0] {
  305. i++
  306. }
  307. dstRune = append(dstRune, strRune[i])
  308. }
  309. return string(dstRune)
  310. }
  311. // 将字符串的IP转化为数字
  312. func Ip4toInt(ip string) int64 {
  313. bits := strings.Split(ip, ".")
  314. if len(bits) == 4 {
  315. b0, _ := strconv.Atoi(bits[0])
  316. b1, _ := strconv.Atoi(bits[1])
  317. b2, _ := strconv.Atoi(bits[2])
  318. b3, _ := strconv.Atoi(bits[3])
  319. var sum int64
  320. sum += int64(b0) << 24
  321. sum += int64(b1) << 16
  322. sum += int64(b2) << 8
  323. sum += int64(b3)
  324. return sum
  325. } else {
  326. return 0
  327. }
  328. }
  329. // 得到当前时间到下一天零点的延时
  330. func NextDayDuration() time.Duration {
  331. year, month, day := time.Now().Add(time.Hour * 24).Date()
  332. next := time.Date(year, month, day, 0, 0, 0, 0, conf.SysTimeLocation)
  333. return next.Sub(time.Now())
  334. }
  335. // 从接口类型安全获取到int64
  336. func GetInt64(i interface{}, d int64) int64 {
  337. if i == nil {
  338. return d
  339. }
  340. switch i.(type) {
  341. case string:
  342. num, err := strconv.Atoi(i.(string))
  343. if err != nil {
  344. return d
  345. } else {
  346. return int64(num)
  347. }
  348. case []byte:
  349. bits := i.([]byte)
  350. if len(bits) == 8 {
  351. return int64(binary.LittleEndian.Uint64(bits))
  352. } else if len(bits) <= 4 {
  353. num, err := strconv.Atoi(string(bits))
  354. if err != nil {
  355. return d
  356. } else {
  357. return int64(num)
  358. }
  359. }
  360. case uint:
  361. return int64(i.(uint))
  362. case uint8:
  363. return int64(i.(uint8))
  364. case uint16:
  365. return int64(i.(uint16))
  366. case uint32:
  367. return int64(i.(uint32))
  368. case uint64:
  369. return int64(i.(uint64))
  370. case int:
  371. return int64(i.(int))
  372. case int8:
  373. return int64(i.(int8))
  374. case int16:
  375. return int64(i.(int16))
  376. case int32:
  377. return int64(i.(int32))
  378. case int64:
  379. return i.(int64)
  380. case float32:
  381. return int64(i.(float32))
  382. case float64:
  383. return int64(i.(float64))
  384. }
  385. return d
  386. }
  387. // 从接口类型安全获取到字符串类型
  388. func GetString(str interface{}, d string) string {
  389. if str == nil {
  390. return d
  391. }
  392. switch str.(type) {
  393. case string:
  394. return str.(string)
  395. case []byte:
  396. return string(str.([]byte))
  397. }
  398. return fmt.Sprintf("%s", str)
  399. }
  400. // 从map中得到指定的key
  401. func GetInt64FromMap(dm map[string]interface{}, key string, dft int64) int64 {
  402. data, ok := dm[key]
  403. if !ok {
  404. return dft
  405. }
  406. return GetInt64(data, dft)
  407. }
  408. // 从map中得到指定的key
  409. func GetInt64FromStringMap(dm map[string]string, key string, dft int64) int64 {
  410. data, ok := dm[key]
  411. if !ok {
  412. return dft
  413. }
  414. return GetInt64(data, dft)
  415. }
  416. // 从map中得到指定的key
  417. func GetStringFromMap(dm map[string]interface{}, key string, dft string) string {
  418. data, ok := dm[key]
  419. if !ok {
  420. return dft
  421. }
  422. return GetString(data, dft)
  423. }
  424. // 从map中得到指定的key
  425. func GetStringFromStringMap(dm map[string]string, key string, dft string) string {
  426. data, ok := dm[key]
  427. if !ok {
  428. return dft
  429. }
  430. return data
  431. }
  432. // 首字母大写
  433. func Ucfirst(str string) string {
  434. for i, v := range str {
  435. return string(unicode.ToUpper(v)) + str[i+1:]
  436. }
  437. return ""
  438. }