This commit is contained in:
孟帅
2022-11-24 23:37:34 +08:00
parent 4ffe54b6ac
commit 29bda0dcdd
1487 changed files with 97869 additions and 96539 deletions

0
server/utility/.gitkeep Normal file
View File

View File

@@ -0,0 +1,45 @@
// Package auth
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package auth
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"hotgo/utility/validate"
)
// IsExceptAuth 是否是不需要验证权限的路由地址
func IsExceptAuth(ctx context.Context, path string) bool {
var pathList []string
except, _ := g.Cfg().Get(ctx, "router.admin.exceptAuth")
pathList = except.Strings()
for i := 0; i < len(pathList); i++ {
if validate.InSliceExistStr(pathList[i], path) {
return true
}
}
return false
}
// IsExceptLogin 是否是不需要登录的路由地址
func IsExceptLogin(ctx context.Context, path string) bool {
var pathList []string
except, _ := g.Cfg().Get(ctx, "router.admin.exceptLogin")
pathList = except.Strings()
for i := 0; i < len(pathList); i++ {
if validate.InSliceExistStr(pathList[i], path) {
return true
}
}
return false
}

View File

@@ -0,0 +1,91 @@
// Package charset
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package charset
import (
"crypto/rand"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/utility/convert"
r "math/rand"
"strings"
"time"
)
// SplitMemberIds 从截取字串符中读取用户ID
func SplitMemberIds(str, pos string) (memberIds []int64) {
receiver := strings.Split(strings.TrimSpace(str), pos)
if len(receiver) == 0 {
return memberIds
}
if len(receiver) == 1 && strings.TrimSpace(receiver[0]) == "" {
return memberIds
}
for _, memberId := range receiver {
memberIds = append(memberIds, gconv.Int64(strings.TrimSpace(memberId)))
}
return convert.UniqueSliceInt64(memberIds)
}
// GetMapKeysByString 获取map的所有key字串符类型
func GetMapKeysByString(m map[string]string) []string {
// 数组默认长度为map长度,后面append时,不需要重新申请内存和拷贝,效率很高
j := 0
keys := make([]string, len(m))
for k := range m {
keys[j] = k
j++
}
return keys
}
// RandomCreateBytes 生成随机字串符
func RandomCreateBytes(n int, alphabets ...byte) []byte {
if len(alphabets) == 0 {
alphabets = []byte(`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`)
}
var bytes = make([]byte, n)
var randBy bool
r.Seed(time.Now().UnixNano())
if num, err := rand.Read(bytes); num != n || err != nil {
randBy = true
}
for i, b := range bytes {
if randBy {
bytes[i] = alphabets[r.Intn(len(alphabets))]
} else {
bytes[i] = alphabets[b%byte(len(alphabets))]
}
}
return bytes
}
// GetStack 格式化错误的堆栈信息
func GetStack(err error) []string {
stackList := gstr.Split(gerror.Stack(err), "\n")
for i := 0; i < len(stackList); i++ {
stackList[i] = gstr.Replace(stackList[i], "\t", "--> ")
}
return stackList
}
// SubstrAfter 截取指定字符后的内容
func SubstrAfter(str string, symbol string) string {
comma := strings.Index(str, symbol)
if comma < 0 { // -1 不存在
return ""
}
pos := strings.Index(str[comma:], symbol)
if comma+pos+1 > len(str) {
return ""
}
return str[comma+pos+1:]
}

View File

@@ -0,0 +1,46 @@
// Package convert
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package convert
// UniqueSliceInt64 切片去重
func UniqueSliceInt64(languages []int64) []int64 {
result := make([]int64, 0, len(languages))
temp := map[int64]struct{}{}
for _, item := range languages {
if _, ok := temp[item]; !ok { //如果字典中找不到元素ok=false!ok为true就往切片中append元素。
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
// InSliceInt64 元素是否存在于切片中
func InSliceInt64(slice []int64, key int64) bool {
if len(slice) == 0 {
return false
}
for i := 0; i < len(slice); i++ {
if slice[i] == key {
return true
}
}
return false
}
// InSliceInt 元素是否存在于切片中
func InSliceInt(slice []int, key int) bool {
if len(slice) == 0 {
return false
}
for i := 0; i < len(slice); i++ {
if slice[i] == key {
return true
}
}
return false
}

View File

@@ -0,0 +1,24 @@
// Package encrypt
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package encrypt
import (
"crypto/md5"
"fmt"
"hash/fnv"
)
// Md5ToString 生成md5
func Md5ToString(str string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(str)))
}
func Hash32(b []byte) uint32 {
h := fnv.New32a()
h.Write(b)
return h.Sum32()
}

View File

@@ -0,0 +1,82 @@
// Package excel
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package excel
import (
"fmt"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/util/gconv"
"github.com/xuri/excelize/v2"
"net/url"
"reflect"
)
func ExportByStruct(w *ghttp.ResponseWriter, titleList []string, data []interface{}, fileName string, sheetName string) error {
f := excelize.NewFile()
f.SetSheetName("Sheet1", sheetName)
header := make([]string, 0)
for _, v := range titleList {
header = append(header, v)
}
rowStyleID, _ := f.NewStyle(`{"font":{"color":"#666666","size":13,"family":"arial"},"alignment":{"vertical":"center","horizontal":"center"}}`)
_ = f.SetSheetRow(sheetName, "A1", &header)
_ = f.SetRowHeight("Sheet1", 1, 30)
length := len(titleList)
headStyle := letter(length)
var lastRow string
var widthRow string
for k, v := range headStyle {
if k == length-1 {
lastRow = fmt.Sprintf("%s1", v)
widthRow = v
}
}
if err := f.SetColWidth(sheetName, "A", widthRow, 30); err != nil {
return err
}
rowNum := 1
for _, v := range data {
t := reflect.TypeOf(v)
value := reflect.ValueOf(v)
row := make([]interface{}, 0)
for l := 0; l < t.NumField(); l++ {
val := value.Field(l).Interface()
row = append(row, val)
}
rowNum++
err := f.SetSheetRow(sheetName, "A"+gconv.String(rowNum), &row)
_ = f.SetCellStyle(sheetName, fmt.Sprintf("A%d", rowNum), fmt.Sprintf("%s", lastRow), rowStyleID)
if err != nil {
return err
}
}
disposition := fmt.Sprintf("attachment; filename=%s.xlsx", url.QueryEscape(fileName))
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", disposition)
w.Header().Set("Content-Transfer-Encoding", "binary")
w.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
err := f.Write(w)
if err != nil {
return err
}
return nil
}
// Letter 遍历a-z
func letter(length int) []string {
var str []string
for i := 0; i < length; i++ {
str = append(str, string(rune('A'+i)))
}
return str
}

113
server/utility/file/file.go Normal file
View File

@@ -0,0 +1,113 @@
// Package file
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package file
import (
"hotgo/utility/format"
"io/ioutil"
"os"
"path/filepath"
)
const ( //文件大小单位
_ = iota
KB = 1 << (10 * iota)
MB
)
type fileInfo struct { //文件信息
name string
size int64
}
func PathExists(path string) (bool, error) {
info, err := os.Stat(path)
if err == nil {
return info.IsDir(), nil
}
return false, err
}
func FileExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
// HasDir 判断文件夹是否存在
func HasDir(path string) (bool, error) {
_, _err := os.Stat(path)
if _err == nil {
return true, nil
}
if os.IsNotExist(_err) {
return false, nil
}
return false, _err
}
// CreateDir 创建文件夹
func CreateDir(path string) (err error) {
_exist, err := HasDir(path)
if err != nil {
return
}
if !_exist {
err = os.Mkdir(path, os.ModePerm)
if err != nil {
return
}
}
return
}
// WalkDir 递归获取目录下文件的名称和大小
func WalkDir(dirname string) (error, []fileInfo) {
op, err := filepath.Abs(dirname) //获取目录的绝对路径
if nil != err {
return err, nil
}
files, err := ioutil.ReadDir(op) //获取目录下所有文件的信息,包括文件和文件夹
if nil != err {
return err, nil
}
var fileInfos []fileInfo //返回值,存储读取的文件信息
for _, f := range files {
if f.IsDir() { // 如果是目录,那么就递归调用
err, fs := WalkDir(op + `/` + f.Name()) //路径分隔符linux 和 windows 不同
if nil != err {
return err, nil
}
fileInfos = append(fileInfos, fs...) //将 slice 添加到 slice
} else {
fi := fileInfo{op + `/` + f.Name(), f.Size()}
fileInfos = append(fileInfos, fi) //slice 中添加成员
}
}
return nil, fileInfos
}
// DirSize 获取目录下所有文件大小
func DirSize(dirname string) string {
var (
ss int64
_, files = WalkDir(dirname)
)
for _, n := range files {
ss += n.size
}
return format.FileSize(ss)
}

147
server/utility/file/mime.go Normal file
View File

@@ -0,0 +1,147 @@
// Package file
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package file
import (
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/text/gstr"
"io/ioutil"
"path"
)
// 文件分类
const (
KindImg = "images" // 图片
KindDoc = "document" // 文档
KindAudio = "audio" // 音频
KindVideo = "video" // 视频
KindOther = "other" // 其他
)
var (
// 图片类型
imgType = g.MapStrStr{
"jpg": "image/jpeg",
"png": "image/png",
"gif": "image/gif",
"webp": "image/webp",
"cr2": "image/x-canon-cr2",
"tif": "image/tiff",
"bmp": "image/bmp",
"heif": "image/heif",
"jxr": "image/vnd.ms-photo",
"psd": "image/vnd.adobe.photoshop",
"ico": "image/vnd.microsoft.icon",
"dwg": "image/vnd.dwg",
}
// 文档类型
docType = g.MapStrStr{
"doc": "application/msword",
"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"xls": "application/vnd.ms-excel",
"xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"ppt": "application/vnd.ms-powerpoint",
"pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
}
// 音频类型
audioType = g.MapStrStr{
"mid": "audio/midi",
"mp3": "audio/mpeg",
"m4a": "audio/mp4",
"ogg": "audio/ogg",
"flac": "audio/x-flac",
"wav": "audio/x-wav",
"amr": "audio/amr",
"aac": "audio/aac",
"aiff": "audio/x-aiff",
}
// 视频类型
videoType = g.MapStrStr{
"mp4": "video/mp4",
"m4v": "video/x-m4v",
"mkv": "video/x-matroska",
"webm": "video/webm",
"mov": "video/quicktime",
"avi": "video/x-msvideo",
"wmv": "video/x-ms-wmv",
"mpg": "video/mpeg",
"flv": "video/x-flv",
"3gp": "video/3gpp",
}
)
// IsImgType 判断是否为图片
func IsImgType(ext string) bool {
_, ok := imgType[ext]
return ok
}
// GetImgType 获取图片类型
func GetImgType(ext string) (string, error) {
if mime, ok := imgType[ext]; ok {
return mime, nil
}
return "", gerror.New("Invalid image type")
}
// GetFileType 获取文件类型
func GetFileType(ext string) (string, error) {
if mime, ok := imgType[ext]; ok {
return mime, nil
}
if mime, ok := docType[ext]; ok {
return mime, nil
}
if mime, ok := audioType[ext]; ok {
return mime, nil
}
if mime, ok := videoType[ext]; ok {
return mime, nil
}
return "", gerror.New("Invalid file type")
}
// GetFileKind 获取文件所属分类
func GetFileKind(ext string) string {
if _, ok := imgType[ext]; ok {
return KindImg
}
if _, ok := docType[ext]; ok {
return KindDoc
}
if _, ok := audioType[ext]; ok {
return KindAudio
}
if _, ok := videoType[ext]; ok {
return KindVideo
}
return KindOther
}
// Ext 获取文件后缀
func Ext(baseName string) string {
return gstr.StrEx(path.Ext(baseName), ".")
}
// UploadFileByte 获取上传文件的byte
func UploadFileByte(file *ghttp.UploadFile) (b []byte, err error) {
open, err := file.Open()
if err != nil {
return
}
all, err := ioutil.ReadAll(open)
if err != nil {
return
}
return all, nil
}

View File

@@ -0,0 +1,55 @@
// Package format
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package format
import (
"fmt"
"github.com/shopspring/decimal"
"math"
)
// RoundInt64 四舍五入
func RoundInt64(x float64) int64 {
return int64(math.Floor(x + 0/5))
}
// Round2String 四舍五入保留小数默认2位
func Round2String(value float64, args ...interface{}) (v string) {
var places int32 = 2
if len(args) > 0 {
places = args[0].(int32)
}
return decimal.NewFromFloat(value).Round(places).String()
}
// Round2Float64 四舍五入保留小数默认2位
func Round2Float64(value float64, args ...interface{}) (v float64) {
var places int32 = 2
if len(args) > 0 {
places = args[0].(int32)
}
return decimal.NewFromFloat(value).Round(places).InexactFloat64()
}
// FileSize 字节的单位转换 保留两位小数
func FileSize(fileSize int64) (size string) {
if fileSize < 1024 {
return fmt.Sprintf("%.2fB", float64(fileSize)/float64(1))
} else if fileSize < (1024 * 1024) {
return fmt.Sprintf("%.2fKB", float64(fileSize)/float64(1024))
} else if fileSize < (1024 * 1024 * 1024) {
return fmt.Sprintf("%.2fMB", float64(fileSize)/float64(1024*1024))
} else if fileSize < (1024 * 1024 * 1024 * 1024) {
return fmt.Sprintf("%.2fGB", float64(fileSize)/float64(1024*1024*1024))
} else if fileSize < (1024 * 1024 * 1024 * 1024 * 1024) {
return fmt.Sprintf("%.2fTB", float64(fileSize)/float64(1024*1024*1024*1024))
} else {
return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
}
}

View File

@@ -0,0 +1,56 @@
// Package signal
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package signal
import (
"sync"
)
type StopSignal int32
type exitWait struct {
mutex sync.Mutex
wg *sync.WaitGroup
deferFuns []func()
stopSignList []chan StopSignal
}
var exitWaitHandler *exitWait
func init() {
exitWaitHandler = &exitWait{
wg: &sync.WaitGroup{},
}
}
// ExitWaitFunDo 退出后等待处理完成
func ExitWaitFunDo(doFun func()) {
exitWaitHandler.wg.Add(1)
defer exitWaitHandler.wg.Done()
if doFun != nil {
doFun()
}
}
// AppDefer 应用退出后置操作
func AppDefer(deferFun ...func()) {
exitWaitHandler.mutex.Lock()
defer exitWaitHandler.mutex.Unlock()
for _, funcItem := range deferFun {
if funcItem != nil {
exitWaitHandler.deferFuns = append(exitWaitHandler.deferFuns, funcItem)
}
}
}
// ListenStop 订阅app退出信号
func ListenStop(stopSig chan StopSignal) {
exitWaitHandler.mutex.Lock()
defer exitWaitHandler.mutex.Unlock()
exitWaitHandler.stopSignList = append(exitWaitHandler.stopSignList, stopSig)
}

View File

@@ -0,0 +1,59 @@
// Package tree
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package tree
import (
"github.com/gogf/gf/v2/util/gconv"
)
var pidName = "pid"
// GenTree 生成关系树 参考https://blog.csdn.net/weixin_51546892/article/details/122876793
func GenTree(menus []map[string]interface{}) (realMenu []map[string]interface{}) {
if len(menus) < 1 {
return nil
}
minPid := GetMinPid(menus)
formatMenu := make(map[int]map[string]interface{})
for _, m := range menus {
formatMenu[gconv.Int(m["id"])] = m
if gconv.Int(m[pidName]) == minPid {
realMenu = append(realMenu, m) // 需要返回的顶级菜单
}
}
// 得益于都是地址操作,可以直接往父级塞
for _, m := range formatMenu {
if formatMenu[gconv.Int(m[pidName])] == nil {
continue
}
if formatMenu[gconv.Int(m[pidName])]["children"] == nil {
formatMenu[gconv.Int(m[pidName])]["children"] = []map[string]interface{}{}
}
formatMenu[gconv.Int(m[pidName])]["children"] = append(formatMenu[gconv.Int(m[pidName])]["children"].([]map[string]interface{}), m)
}
return
}
func GetMinPid(menus []map[string]interface{}) int {
index := -1
for _, m := range menus {
if index == -1 {
index = gconv.Int(m[pidName])
continue
}
if gconv.Int(m[pidName]) < index {
index = gconv.Int(m[pidName])
}
}
if index == -1 {
return 0
}
return index
}

View File

@@ -0,0 +1,125 @@
// Package useragent
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package useragent
import (
"fmt"
"regexp"
"strings"
)
// GetOs 获取OS名称
func GetOs(userAgent string) string {
osName := "Unknown"
if userAgent == "" {
return osName
}
strRe, _ := regexp.Compile("(?i:\\((.*?)\\))")
userAgent = strRe.FindString(userAgent)
levelNames := ":micromessenger:dart:Windows NT:Windows Mobile:Windows Phone:Windows Phone OS:Macintosh|Macintosh:Mac OS:CrOS|CrOS:iPhone OS:iPad|iPad:OS:Android:Linux:blackberry:hpwOS:Series:Symbian:PalmOS:SymbianOS:J2ME:Sailfish:Bada:MeeGo:webOS|hpwOS:Maemo:"
var regStrArr []string
namesArr := strings.Split(strings.Trim(levelNames, ":"), ":")
for _, name := range namesArr {
regStrArr = append(regStrArr, fmt.Sprintf("(%s[\\s?\\/XxSs0-9_.]+)", name))
}
regexpStr := fmt.Sprintf("(?i:%s)", strings.Join(regStrArr, "|"))
nameRe, _ := regexp.Compile(regexpStr)
names := nameRe.FindAllString(userAgent, -1)
name := ""
for _, s := range names {
if name == "" {
name = strings.TrimSpace(s)
} else if len(name) > 0 {
if strings.Contains(name, "Macintosh") && s != "" {
name = strings.TrimSpace(s)
} else if strings.Contains(name, s) {
name = strings.TrimSpace(s)
} else if !strings.Contains(s, name) {
if strings.Contains(name, "iPhone") ||
strings.Contains(name, "iPad") {
s = strings.Trim(s, "Mac OS X")
}
if s != "" {
name += " " + strings.TrimSpace(s)
}
}
break
}
if strings.Contains(name, "Windows NT") {
name = getWinOsNameWithWinNT(name)
break
}
}
if name != "" {
osName = name
}
return osName
}
// GetBrowser 获取浏览器名称
func GetBrowser(userAgent string) string {
deviceName := "Unknown"
levelNames := ":VivoBrowser:QQDownload:QQBrowser:QQ:MQQBrowser:MicroMessenger:TencentTraveler:LBBROWSER:TaoBrowser:BrowserNG:UCWEB:TwonkyBeamBrowser:NokiaBrowser:OviBrowser:NF-Browser:OneBrowser:Obigo:DiigoBrowser:baidubrowser:baiduboxapp:xiaomi:Redmi:MI:Lumia:Micromax:MSIEMobile:IEMobile:EdgiOS:Yandex:Mercury:Openwave:TouchPad:UBrowser:Presto:Maxthon:MetaSr:Trident:Opera:IEMobile:Edge:Chrome:Chromium:OPR:CriOS:Firefox:FxiOS:fennec:CrMo:Safari:Nexus One:Nexus S:Nexus:Blazer:teashark:bolt:HTC:Dell:Motorola:Samsung:LG:Sony:SonyST:SonyLT:SonyEricsson:Asus:Palm:Vertu:Pantech:Fly:Wiko:i-mobile:Alcatel:Nintendo:Amoi:INQ:ONEPLUS:Tapatalk:PDA:Novarra-Vision:NetFront:Minimo:FlyFlow:Dolfin:Nokia:Series:AppleWebKit:Mobile:Mozilla:Version:"
var regStrArr []string
namesArr := strings.Split(strings.Trim(levelNames, ":"), ":")
for _, name := range namesArr {
regStrArr = append(regStrArr, fmt.Sprintf("(%s[\\s?\\/0-9.]+)", name))
}
regexpStr := fmt.Sprintf("(?i:%s)", strings.Join(regStrArr, "|"))
nameRe, _ := regexp.Compile(regexpStr)
names := nameRe.FindAllString(userAgent, -1)
level := 0
for _, name := range names {
replaceRe, _ := regexp.Compile("(?i:[\\s?\\/0-9.]+)")
n := replaceRe.ReplaceAllString(name, "")
l := strings.Index(levelNames, fmt.Sprintf(":%s:", n))
if level == 0 {
deviceName = strings.TrimSpace(name)
}
if l >= 0 && (level == 0 || level > l) {
level = l
deviceName = strings.TrimSpace(name)
}
}
return deviceName
}
func getWinOsNameWithWinNT(sName string) string {
osName := "Windows"
types := map[string]string{
"Windows NT 10": "Windows 10",
"Windows NT 6.3": "Windows 8",
"Windows NT 6.2": "Windows 8",
"Windows NT 6.1": "Windows 7",
"Windows NT 6.0": "Windows Vista/Server 2008",
"Windows NT 5.2": "Windows Server 2003",
"Windows NT 5.1": "Windows XP",
"Windows NT 5": "Windows 2000",
"Windows NT 4": "Windows NT4",
}
for keyWord, name := range types {
if strings.Contains(sName, keyWord) {
osName = name
break
}
}
return osName
}

View File

@@ -0,0 +1,78 @@
// Package validate
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package validate
import (
"github.com/gogf/gf/v2/util/gconv"
"net"
"net/url"
"regexp"
"time"
)
// IsIp 是否为ipv4
func IsIp(ip string) bool {
if net.ParseIP(ip) != nil {
return true
}
return false
}
// IsEmail 是否为邮箱地址
func IsEmail(email string) bool {
//pattern := `\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*` //匹配电子邮箱
pattern := `^[0-9a-z][_.0-9a-z-]{0,31}@([0-9a-z][0-9a-z-]{0,30}[0-9a-z].){1,4}[a-z]{2,4}$`
reg := regexp.MustCompile(pattern)
return reg.MatchString(email)
}
// InSameDay 是否为同一天
func InSameDay(t1, t2 int64) bool {
y1, m1, d1 := time.Unix(t1, 0).Date()
y2, m2, d2 := time.Unix(t2, 0).Date()
return y1 == y2 && m1 == m2 && d1 == d2
}
// InSameMinute 是否为同一分钟
func InSameMinute(t1, t2 int64) bool {
d1 := time.Unix(t1, 0).Format("2006-01-02 15:04")
d2 := time.Unix(t2, 0).Format("2006-01-02 15:04")
return d1 == d2
}
// InSliceExistStr 判断字符或切片字符是否存在指定字符
func InSliceExistStr(elems interface{}, search string) bool {
switch elems.(type) {
case []string:
elem := gconv.Strings(elems)
for i := 0; i < len(elem); i++ {
if gconv.String(elem[i]) == search {
return true
}
}
default:
return gconv.String(elems) == search
}
return false
}
// IsURL 是否是url地址
func IsURL(u string) bool {
_, err := url.ParseRequestURI(u)
if err != nil {
return false
}
URL, err := url.Parse(u)
if err != nil || URL.Scheme == "" || URL.Host == "" {
return false
}
return true
}