|  |  |  |  | package Common | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"crypto/md5" | 
					
						
							|  |  |  |  | 	"encoding/hex" | 
					
						
							|  |  |  |  | 	"encoding/json" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"io" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"net" | 
					
						
							|  |  |  |  | 	"os" | 
					
						
							|  |  |  |  | 	"os/exec" | 
					
						
							|  |  |  |  | 	"path" | 
					
						
							|  |  |  |  | 	"reflect" | 
					
						
							|  |  |  |  | 	"strconv" | 
					
						
							|  |  |  |  | 	"strings" | 
					
						
							|  |  |  |  | 	"time" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	log "github.com/sirupsen/logrus" | 
					
						
							|  |  |  |  | 	// "github.com/faiface/beep/speaker"
 | 
					
						
							|  |  |  |  | 	// log "github.com/sirupsen/logrus"
 | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 截取字符串 start 起点下标 length 需要截取的长度
 | 
					
						
							|  |  |  |  | func Substr(str string, start int, length int) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("Substr:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	rs := []rune(str) | 
					
						
							|  |  |  |  | 	rl := len(rs) | 
					
						
							|  |  |  |  | 	end := 0 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if start < 0 { | 
					
						
							|  |  |  |  | 		start = rl - 1 + start | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	end = start + length | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if start > end { | 
					
						
							|  |  |  |  | 		start, end = end, start | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if start < 0 { | 
					
						
							|  |  |  |  | 		start = 0 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if start > rl { | 
					
						
							|  |  |  |  | 		start = rl | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if end < 0 { | 
					
						
							|  |  |  |  | 		end = 0 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if end > rl { | 
					
						
							|  |  |  |  | 		end = rl | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return string(rs[start:end]) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // insertSlice 插入
 | 
					
						
							|  |  |  |  | func InsertSlice(index int, newstr []byte, src []byte) (ns []byte) { | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("InsertSlice:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 	ns = append(ns, src[:index]...) // 切片后加..., 相当于拆包成单个元素
 | 
					
						
							|  |  |  |  | 	ns = append(ns, newstr...) | 
					
						
							|  |  |  |  | 	ns = append(ns, src[index+len(newstr):]...) | 
					
						
							|  |  |  |  | 	return | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func InsertToSlice(index int, newstr []byte, src []byte) (ns []byte) { | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("InsertToSlice:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 	ns = append(ns, src[:index]...) // 切片后加..., 相当于拆包成单个元素
 | 
					
						
							|  |  |  |  | 	ns = append(ns, newstr...) | 
					
						
							|  |  |  |  | 	ns = append(ns, src[index:]...) | 
					
						
							|  |  |  |  | 	return | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func ContainCS(list []string, key string) bool { | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("ContainCS:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for _, item := range list { | 
					
						
							|  |  |  |  | 		if item == key { | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Contain(obj interface{}, target interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("Contain:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	targetValue := reflect.ValueOf(target) | 
					
						
							|  |  |  |  | 	switch reflect.TypeOf(target).Kind() { | 
					
						
							|  |  |  |  | 	case reflect.Slice, reflect.Array: | 
					
						
							|  |  |  |  | 		for i := 0; i < targetValue.Len(); i++ { | 
					
						
							|  |  |  |  | 			if targetValue.Index(i).Interface() == obj { | 
					
						
							|  |  |  |  | 				return true | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case reflect.Map: | 
					
						
							|  |  |  |  | 		if targetValue.MapIndex(reflect.ValueOf(obj)).IsValid() { | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // RemoveElementToint32 移除数组内的指定元素
 | 
					
						
							|  |  |  |  | func RemoveElementStrings(list []string, value string) []string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("RemoveElementStrings:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var result = make([]string, 0) | 
					
						
							|  |  |  |  | 	index := 0 | 
					
						
							|  |  |  |  | 	endIndex := len(list) - 1 | 
					
						
							|  |  |  |  | 	for i, s := range list { | 
					
						
							|  |  |  |  | 		if s == value { | 
					
						
							|  |  |  |  | 			result = append(result, list[index:i]...) | 
					
						
							|  |  |  |  | 			index = i + 1 | 
					
						
							|  |  |  |  | 		} else if i == endIndex { | 
					
						
							|  |  |  |  | 			result = append(result, list[index:endIndex+1]...) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return result | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Strval 获取变量的字符串值
 | 
					
						
							|  |  |  |  | // 浮点型 3.0将会转换成字符串3, "3"
 | 
					
						
							|  |  |  |  | // 非数值或字符类型的变量将会被转换成JSON格式字符串
 | 
					
						
							|  |  |  |  | func Strval(value interface{}) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("Strval:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var key string | 
					
						
							|  |  |  |  | 	if value == nil { | 
					
						
							|  |  |  |  | 		return key | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	switch value.(type) { | 
					
						
							|  |  |  |  | 	case float64: | 
					
						
							|  |  |  |  | 		ft := value.(float64) | 
					
						
							|  |  |  |  | 		key = strconv.FormatFloat(ft, 'f', -1, 64) | 
					
						
							|  |  |  |  | 	case float32: | 
					
						
							|  |  |  |  | 		ft := value.(float32) | 
					
						
							|  |  |  |  | 		key = strconv.FormatFloat(float64(ft), 'f', -1, 64) | 
					
						
							|  |  |  |  | 	case int: | 
					
						
							|  |  |  |  | 		it := value.(int) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(it) | 
					
						
							|  |  |  |  | 	case uint: | 
					
						
							|  |  |  |  | 		it := value.(uint) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case int8: | 
					
						
							|  |  |  |  | 		it := value.(int8) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case uint8: | 
					
						
							|  |  |  |  | 		it := value.(uint8) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case int16: | 
					
						
							|  |  |  |  | 		it := value.(int16) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case uint16: | 
					
						
							|  |  |  |  | 		it := value.(uint16) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case int32: | 
					
						
							|  |  |  |  | 		it := value.(int32) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case uint32: | 
					
						
							|  |  |  |  | 		it := value.(uint32) | 
					
						
							|  |  |  |  | 		key = strconv.Itoa(int(it)) | 
					
						
							|  |  |  |  | 	case int64: | 
					
						
							|  |  |  |  | 		it := value.(int64) | 
					
						
							|  |  |  |  | 		key = strconv.FormatInt(it, 10) | 
					
						
							|  |  |  |  | 	case uint64: | 
					
						
							|  |  |  |  | 		it := value.(uint64) | 
					
						
							|  |  |  |  | 		key = strconv.FormatUint(it, 10) | 
					
						
							|  |  |  |  | 	case string: | 
					
						
							|  |  |  |  | 		key = value.(string) | 
					
						
							|  |  |  |  | 	case []byte: | 
					
						
							|  |  |  |  | 		key = string(value.([]byte)) | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		newValue, _ := json.Marshal(value) | 
					
						
							|  |  |  |  | 		key = string(newValue) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return key | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // MD5加密
 | 
					
						
							|  |  |  |  | func GetAuthKey(token string) (key string) { | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("GetAuthKey:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	token = token | 
					
						
							|  |  |  |  | 	md5Ctx := md5.New() | 
					
						
							|  |  |  |  | 	md5Ctx.Write([]byte(token)) | 
					
						
							|  |  |  |  | 	data := md5Ctx.Sum(nil) | 
					
						
							|  |  |  |  | 	return hex.EncodeToString(data) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /** | 
					
						
							|  |  |  |  | *@tips l.ibreoffice 转换指令: | 
					
						
							|  |  |  |  | * libreoffice6.2 invisible --convert-to pdf csDoc.doc --outdir /home/[转出目录] | 
					
						
							|  |  |  |  | * | 
					
						
							|  |  |  |  | * @function 实现文档类型转换为pdf或html | 
					
						
							|  |  |  |  | * @param command:libreofficed的命令(具体以版本为准);win:soffice; linux:libreoffice6.2 | 
					
						
							|  |  |  |  | *     fileSrcPath:转换文件的路径 | 
					
						
							|  |  |  |  | *     fileOutDir:转换后文件存储目录 | 
					
						
							|  |  |  |  | *     converterType:转换的类型pdf/html | 
					
						
							|  |  |  |  | * @return fileOutPath 转换成功生成的文件的路径 error 转换错误 | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | func FuncDocs2Pdf(command string, fileSrcPath string, fileOutDir string, converterType string) (fileOutPath string, error error) { | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("FuncDocs2Pdf:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	//校验fileSrcPath
 | 
					
						
							|  |  |  |  | 	srcFile, erByOpenSrcFile := os.Open(fileSrcPath) | 
					
						
							|  |  |  |  | 	if erByOpenSrcFile != nil && os.IsNotExist(erByOpenSrcFile) { | 
					
						
							|  |  |  |  | 		return "", erByOpenSrcFile | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//如文件输出目录fileOutDir不存在则自动创建
 | 
					
						
							|  |  |  |  | 	outFileDir, erByOpenFileOutDir := os.Open(fileOutDir) | 
					
						
							|  |  |  |  | 	if erByOpenFileOutDir != nil && os.IsNotExist(erByOpenFileOutDir) { | 
					
						
							|  |  |  |  | 		erByCreateFileOutDir := os.MkdirAll(fileOutDir, os.ModePerm) | 
					
						
							|  |  |  |  | 		if erByCreateFileOutDir != nil { | 
					
						
							|  |  |  |  | 			fmt.Println("File ouput dir create error.....", erByCreateFileOutDir.Error()) | 
					
						
							|  |  |  |  | 			return "", erByCreateFileOutDir | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//关闭流
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		_ = srcFile.Close() | 
					
						
							|  |  |  |  | 		_ = outFileDir.Close() | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 	//convert
 | 
					
						
							|  |  |  |  | 	cmd := exec.Command(command, "--invisible", "--language=zh-CN", "--convert-to", converterType, | 
					
						
							|  |  |  |  | 		fileSrcPath, "--outdir", fileOutDir) | 
					
						
							|  |  |  |  | 	byteByStat, errByCmdStart := cmd.Output() | 
					
						
							|  |  |  |  | 	//命令调用转换失败
 | 
					
						
							|  |  |  |  | 	if errByCmdStart != nil { | 
					
						
							|  |  |  |  | 		return "", errByCmdStart | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//success
 | 
					
						
							|  |  |  |  | 	fileOutPath = fileOutDir + "/" + strings.Split(path.Base(fileSrcPath), ".")[0] | 
					
						
							|  |  |  |  | 	if converterType == "html" { | 
					
						
							|  |  |  |  | 		fileOutPath += ".html" | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		fileOutPath += ".pdf" | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	fmt.Println("文件转换成功...", string(byteByStat)) | 
					
						
							|  |  |  |  | 	return fileOutPath, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 中文转拼音函数
 | 
					
						
							|  |  |  |  | func ToPinYin(words string) string { | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("ToPinYin:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	//fmt.Println("words",words)
 | 
					
						
							|  |  |  |  | 	var name string | 
					
						
							|  |  |  |  | 	flag := 0 | 
					
						
							|  |  |  |  | 	for _, n := range words { | 
					
						
							|  |  |  |  | 		flag++ | 
					
						
							|  |  |  |  | 		//fmt.Println("n:",strings.Replace(string(n)," ","",-1))
 | 
					
						
							|  |  |  |  | 		if (strings.Compare(strings.Replace(string(n), " ", "", -1), "覃") == 0) && (flag == 1) { | 
					
						
							|  |  |  |  | 			name += firstNamePin(string(n)) | 
					
						
							|  |  |  |  | 			flag = 0 | 
					
						
							|  |  |  |  | 		} else if (strings.Compare(strings.Replace(string(n), " ", "", -1), "区") == 0) && (flag == 1) { | 
					
						
							|  |  |  |  | 			name += firstNamePin(string(n)) | 
					
						
							|  |  |  |  | 			flag = 0 | 
					
						
							|  |  |  |  | 		} else if (strings.Compare(strings.Replace(string(n), " ", "", -1), "牟") == 0) && (flag == 1) { | 
					
						
							|  |  |  |  | 			name += firstNamePin(string(n)) | 
					
						
							|  |  |  |  | 			flag = 0 | 
					
						
							|  |  |  |  | 		} else if (strings.Compare(strings.Replace(string(n), " ", "", -1), "单") == 0) && (flag == 1) { | 
					
						
							|  |  |  |  | 			name += firstNamePin(string(n)) | 
					
						
							|  |  |  |  | 			flag = 0 | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			// str, err := pinyin.New(string(n)).Split("").Mode(pinyin.InitialsInCapitals).Convert()
 | 
					
						
							|  |  |  |  | 			// if err != nil {
 | 
					
						
							|  |  |  |  | 			// 	fmt.Println("转换拼音异常...")
 | 
					
						
							|  |  |  |  | 			// } else {
 | 
					
						
							|  |  |  |  | 			// 	name += str
 | 
					
						
							|  |  |  |  | 			// }
 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return name | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 多音字解决方法,尤其是姓氏
 | 
					
						
							|  |  |  |  | func firstNamePin(name string) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("firstNamePin:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var n string | 
					
						
							|  |  |  |  | 	//fmt.Println("name:",name)
 | 
					
						
							|  |  |  |  | 	n = "" | 
					
						
							|  |  |  |  | 	if strings.Compare(name, "覃") == 0 { | 
					
						
							|  |  |  |  | 		n = "Qin" | 
					
						
							|  |  |  |  | 	} else if strings.Compare(name, "区") == 0 { | 
					
						
							|  |  |  |  | 		n = "Ou" | 
					
						
							|  |  |  |  | 	} else if strings.Compare(name, "牟") == 0 { | 
					
						
							|  |  |  |  | 		n = "Mu" | 
					
						
							|  |  |  |  | 	} else if strings.Compare(name, "单") == 0 { | 
					
						
							|  |  |  |  | 		n = "Shan" | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return n | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func DeleteFile(Path string) (total int64, err error) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("DeleteFile:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if Path != "" { | 
					
						
							|  |  |  |  | 		err = os.Remove(Path) //删除文件
 | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			//如果删除失败则输出 file remove Error!
 | 
					
						
							|  |  |  |  | 			fmt.Println("file remove Error!") | 
					
						
							|  |  |  |  | 			//输出错误详细信息
 | 
					
						
							|  |  |  |  | 			fmt.Printf("%s", err) | 
					
						
							|  |  |  |  | 			return 0, err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return 1, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return 2, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func PathExists(path string) (bool, error) { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("PathExists:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	_, err := os.Stat(path) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return true, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if os.IsNotExist(err) { | 
					
						
							|  |  |  |  | 		return false, nil | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false, nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /** | 
					
						
							|  |  |  |  |  * 判断文件是否存在  存在返回 true 不存在返回false | 
					
						
							|  |  |  |  |  */ | 
					
						
							|  |  |  |  | func CheckFileIsExists(filename string) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("CheckFileIsExists:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var exist = true | 
					
						
							|  |  |  |  | 	if _, err := os.Stat(filename); os.IsNotExist(err) { | 
					
						
							|  |  |  |  | 		exist = false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return exist | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* | 
					
						
							|  |  |  |  | * | 
					
						
							|  |  |  |  | 判断文件是否存在 | 
					
						
							|  |  |  |  | */ | 
					
						
							|  |  |  |  | func IsDirs(fileAddr string) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("IsDirs:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	s, err := os.Stat(fileAddr) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		log.Println(err) | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return s.IsDir() | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | /* | 
					
						
							|  |  |  |  | 极光推送:go向Android推送消息 | 
					
						
							|  |  |  |  | */ | 
					
						
							|  |  |  |  | // func JpushGoSend(tags []string, aliasPhone []string, context string, state, jpushState int) error {
 | 
					
						
							|  |  |  |  | // 	//state:区分推送方式;  jpushState :区分推送消息的类别;
 | 
					
						
							|  |  |  |  | // 	//构建要推送的平台: jpushclient.Platform
 | 
					
						
							|  |  |  |  | // 	var pf jpushclient.Platform
 | 
					
						
							|  |  |  |  | // 	pf.Add(jpushclient.ANDROID)
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	//构建接收听众: jpushclient.Audience
 | 
					
						
							|  |  |  |  | // 	var ad jpushclient.Audience
 | 
					
						
							|  |  |  |  | // 	if state == JpushTag {
 | 
					
						
							|  |  |  |  | // 		//推送 通知公告
 | 
					
						
							|  |  |  |  | // 		if tags[0] == AdminLevelOne {
 | 
					
						
							|  |  |  |  | // 			//极光推送 - 所有
 | 
					
						
							|  |  |  |  | // 			//一级管理员发布,所有人员接收
 | 
					
						
							|  |  |  |  | // 			ad.All()
 | 
					
						
							|  |  |  |  | // 		} else {
 | 
					
						
							|  |  |  |  | // 			//极光推送 - tag
 | 
					
						
							|  |  |  |  | // 			//二级或者三级管理员发布,下属app人员接收
 | 
					
						
							|  |  |  |  | // 			ad.SetTag(tags)
 | 
					
						
							|  |  |  |  | // 		}
 | 
					
						
							|  |  |  |  | // 	} else {
 | 
					
						
							|  |  |  |  | // 		//极光推送 - 别名 ,用app用户的登录手机号当作别名
 | 
					
						
							|  |  |  |  | // 		ad.SetAlias(aliasPhone)
 | 
					
						
							|  |  |  |  | // 	}
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	//构建通知 jpushclient.Notice,或者消息: jpushclient.Message
 | 
					
						
							|  |  |  |  | // 	//Notice
 | 
					
						
							|  |  |  |  | // 	var notice jpushclient.Notice
 | 
					
						
							|  |  |  |  | // 	notice.SetAlert("alert_test")
 | 
					
						
							|  |  |  |  | // 	if jpushState == JpushStateNotice {
 | 
					
						
							|  |  |  |  | // 		//推送通知公告
 | 
					
						
							|  |  |  |  | // 		notice.SetAndroidNotice(&jpushclient.AndroidNotice{Title: "通知公告", Alert: context})
 | 
					
						
							|  |  |  |  | // 	} else {
 | 
					
						
							|  |  |  |  | // 		//推送新单
 | 
					
						
							|  |  |  |  | // 		notice.SetAndroidNotice(&jpushclient.AndroidNotice{Title: "新派xx单", Alert: context})
 | 
					
						
							|  |  |  |  | // 	}
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	//构建jpushclient.PayLoad
 | 
					
						
							|  |  |  |  | // 	payload := jpushclient.NewPushPayLoad()
 | 
					
						
							|  |  |  |  | // 	payload.SetPlatform(&pf)
 | 
					
						
							|  |  |  |  | // 	payload.SetAudience(&ad)
 | 
					
						
							|  |  |  |  | // 	payload.SetNotice(¬ice)
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	bytes, _ := payload.ToBytes()
 | 
					
						
							|  |  |  |  | // 	fmt.Printf("%s\r\n", string(bytes))
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	//构建PushClient,发出推送
 | 
					
						
							|  |  |  |  | // 	c := jpushclient.NewPushClient(masterSecret, appKey)
 | 
					
						
							|  |  |  |  | // 	r, err := c.Send(bytes)
 | 
					
						
							|  |  |  |  | // 	if err != nil {
 | 
					
						
							|  |  |  |  | // 		fmt.Printf("err:%s", err.Error())
 | 
					
						
							|  |  |  |  | // 		return err
 | 
					
						
							|  |  |  |  | // 	} else {
 | 
					
						
							|  |  |  |  | // 		fmt.Printf("ok:%s", r)
 | 
					
						
							|  |  |  |  | // 	}
 | 
					
						
							|  |  |  |  | // 	return nil
 | 
					
						
							|  |  |  |  | // }
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func intToChinese(num int) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("intToChinese:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	chineseNums := []string{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"} | 
					
						
							|  |  |  |  | 	chineseUnits := []string{"", "十", "百", "千"} | 
					
						
							|  |  |  |  | 	chineseBigUnits := []string{"", "万", "亿", "万亿"} // 可根据需求扩展更大的单位
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var result strings.Builder | 
					
						
							|  |  |  |  | 	zero := true // 是否需要补零
 | 
					
						
							|  |  |  |  | 	unit := 0    // 当前的单位
 | 
					
						
							|  |  |  |  | 	for num > 0 { | 
					
						
							|  |  |  |  | 		n := num % 10 | 
					
						
							|  |  |  |  | 		if n > 0 { | 
					
						
							|  |  |  |  | 			if zero { | 
					
						
							|  |  |  |  | 				result.WriteString(chineseNums[0]) // 如果需要补零,则先补零
 | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			result.WriteString(chineseNums[n]) | 
					
						
							|  |  |  |  | 			result.WriteString(chineseUnits[unit]) | 
					
						
							|  |  |  |  | 			zero = false | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			zero = true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		unit++ | 
					
						
							|  |  |  |  | 		if unit == 4 { // 单位循环
 | 
					
						
							|  |  |  |  | 			unit = 0 | 
					
						
							|  |  |  |  | 			result.WriteString(chineseBigUnits[unit]) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		num /= 10 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return reverseString(result.String()) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 反转字符串
 | 
					
						
							|  |  |  |  | func reverseString(s string) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("reverseString:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	r := []rune(s) | 
					
						
							|  |  |  |  | 	for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 { | 
					
						
							|  |  |  |  | 		r[i], r[j] = r[j], r[i] | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return string(r) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func MapsAreEqual(map1, map2 map[string]interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("MapsAreEqual:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查长度是否相等
 | 
					
						
							|  |  |  |  | 	if len(map1) != len(map2) { | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 遍历 map1 的键值对
 | 
					
						
							|  |  |  |  | 	for key, value := range map1 { | 
					
						
							|  |  |  |  | 		// 检查 map2 中是否存在相同的键
 | 
					
						
							|  |  |  |  | 		if value2, ok := map2[key]; ok { | 
					
						
							|  |  |  |  | 			// 递归比较值
 | 
					
						
							|  |  |  |  | 			if !valuesAreEqual(value, value2) { | 
					
						
							|  |  |  |  | 				return false | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			// map2 中不存在相同的键
 | 
					
						
							|  |  |  |  | 			return false | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return true | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func valuesAreEqual(value1, value2 interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("valuesAreEqual:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 判断类型是否相同
 | 
					
						
							|  |  |  |  | 	if reflect.TypeOf(value1) != reflect.TypeOf(value2) { | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 对不同类型的值进行比较
 | 
					
						
							|  |  |  |  | 	switch value1 := value1.(type) { | 
					
						
							|  |  |  |  | 	case map[string]interface{}: | 
					
						
							|  |  |  |  | 		return MapsAreEqual(value1, value2.(map[string]interface{})) | 
					
						
							|  |  |  |  | 	case []interface{}: | 
					
						
							|  |  |  |  | 		return slicesAreEqual(value1, value2.([]interface{})) | 
					
						
							|  |  |  |  | 	case []map[string]interface{}: | 
					
						
							|  |  |  |  | 		return slicesmapAreEqual(value1, value2.([]map[string]interface{})) | 
					
						
							|  |  |  |  | 	case int, int32, int64, uint, uint32, uint64, float32, float64, string, bool, time.Time: | 
					
						
							|  |  |  |  | 		// 基本类型直接比较值
 | 
					
						
							|  |  |  |  | 		return value1 == value2 | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		return structValuesAreEqual(value1, value2) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func structValuesAreEqual(value1, value2 interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("structValuesAreEqual:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 获取 value1 和 value2 的反射值
 | 
					
						
							|  |  |  |  | 	v1 := reflect.ValueOf(value1) | 
					
						
							|  |  |  |  | 	v2 := reflect.ValueOf(value2) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 判断类型是否相同
 | 
					
						
							|  |  |  |  | 	if v1.Type() != v2.Type() { | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 遍历结构体的字段
 | 
					
						
							|  |  |  |  | 	for i := 0; i < v1.NumField(); i++ { | 
					
						
							|  |  |  |  | 		// 获取字段的反射值和名称
 | 
					
						
							|  |  |  |  | 		field1 := v1.Field(i) | 
					
						
							|  |  |  |  | 		field2 := v2.Field(i) | 
					
						
							|  |  |  |  | 		name := v1.Type().Field(i).Name | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// 递归比较属性值
 | 
					
						
							|  |  |  |  | 		if !valuesAreEqual(field1.Interface(), field2.Interface()) { | 
					
						
							|  |  |  |  | 			fmt.Printf("%s: %v != %v\n", name, field1.Interface(), field2.Interface()) | 
					
						
							|  |  |  |  | 			return false | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return true | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func slicesmapAreEqual(slice1, slice2 []map[string]interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("slicesmapAreEqual:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查长度是否相等
 | 
					
						
							|  |  |  |  | 	if len(slice1) != len(slice2) { | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 递归比较每个元素
 | 
					
						
							|  |  |  |  | 	for i := 0; i < len(slice1); i++ { | 
					
						
							|  |  |  |  | 		if !valuesAreEqual(slice1[i], slice2[i]) { | 
					
						
							|  |  |  |  | 			return false | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return true | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func slicesAreEqual(slice1, slice2 []interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("slicesAreEqual:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 检查长度是否相等
 | 
					
						
							|  |  |  |  | 	if len(slice1) != len(slice2) { | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 递归比较每个元素
 | 
					
						
							|  |  |  |  | 	for i := 0; i < len(slice1); i++ { | 
					
						
							|  |  |  |  | 		if !valuesAreEqual(slice1[i], slice2[i]) { | 
					
						
							|  |  |  |  | 			return false | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return true | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // IsNullOrEmpty 检查字符串是否为空或为nil
 | 
					
						
							|  |  |  |  | func IsNullOrEmpty(s *string) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("IsNullOrEmpty:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if s == nil || *s == "" { | 
					
						
							|  |  |  |  | 		return true | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Contains(slice []interface{}, item interface{}) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("Contains:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for _, sliceItem := range slice { | 
					
						
							|  |  |  |  | 		if sliceItem == item { | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return false | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func CreateMutiDir(filePath string) error { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("CreateMutiDir:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if !isExist(filePath) { | 
					
						
							|  |  |  |  | 		err := os.MkdirAll(filePath, os.ModePerm) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			fmt.Println("创建文件夹失败,error info:", err) | 
					
						
							|  |  |  |  | 			return err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 判断所给路径文件/文件夹是否存在(返回true是存在)
 | 
					
						
							|  |  |  |  | func isExist(path string) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("isExist:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	_, err := os.Stat(path) //os.Stat获取文件信息
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		if os.IsExist(err) { | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return true | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func IsExist(path string) bool { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("IsExist:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	_, err := os.Stat(path) //os.Stat获取文件信息
 | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		if os.IsExist(err) { | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return true | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func StructToMap(obj interface{}) map[string]interface{} { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("StructToMap:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	objValue := reflect.ValueOf(obj) | 
					
						
							|  |  |  |  | 	if objValue.Kind() == reflect.Ptr { | 
					
						
							|  |  |  |  | 		objValue = objValue.Elem() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if objValue.Kind() != reflect.Struct { | 
					
						
							|  |  |  |  | 		panic("传入的不是结构体类型") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	objType := objValue.Type() | 
					
						
							|  |  |  |  | 	result := make(map[string]interface{}) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for i := 0; i < objValue.NumField(); i++ { | 
					
						
							|  |  |  |  | 		field := objValue.Field(i) | 
					
						
							|  |  |  |  | 		fieldName := objType.Field(i).Name | 
					
						
							|  |  |  |  | 		result[fieldName] = field.Interface() | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return result | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func GetLocalIP() string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("GetLocalIP:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var IPAddress string = "127.0.0.1" | 
					
						
							|  |  |  |  | 	netInterfaces, err := net.Interfaces() | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		fmt.Println("net.Interfaces failed, err:", err.Error()) | 
					
						
							|  |  |  |  | 		return IPAddress | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for i := 0; i < len(netInterfaces); i++ { | 
					
						
							|  |  |  |  | 		if (netInterfaces[i].Flags & net.FlagUp) != 0 { | 
					
						
							|  |  |  |  | 			addrs, _ := netInterfaces[i].Addrs() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			for _, address := range addrs { | 
					
						
							|  |  |  |  | 				if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { | 
					
						
							|  |  |  |  | 					if ipnet.IP.To4() != nil { | 
					
						
							|  |  |  |  | 						IPAddress = ipnet.IP.String() | 
					
						
							|  |  |  |  | 						return IPAddress | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return IPAddress | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func Md5func(filePath string) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("Md5func:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 打开文件
 | 
					
						
							|  |  |  |  | 	file, err := os.Open(filePath) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		fmt.Println("无法打开文件:", err) | 
					
						
							|  |  |  |  | 		return "" | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	defer file.Close() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 创建一个 MD5 的哈希对象
 | 
					
						
							|  |  |  |  | 	hash := md5.New() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 将文件内容拷贝到哈希对象中
 | 
					
						
							|  |  |  |  | 	if _, err := io.Copy(hash, file); err != nil { | 
					
						
							|  |  |  |  | 		fmt.Println("无法读取文件内容:", err) | 
					
						
							|  |  |  |  | 		return "" | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 计算 MD5 哈希值
 | 
					
						
							|  |  |  |  | 	hashInBytes := hash.Sum(nil) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 将字节转换为十六进制表示
 | 
					
						
							|  |  |  |  | 	md5Hash := hex.EncodeToString(hashInBytes) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	fmt.Printf("文件 %s 的MD5哈希值为: %s\n", filePath, md5Hash) | 
					
						
							|  |  |  |  | 	return md5Hash | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func PlayMusic(musicPath string) error { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("PlayMusic:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 打开wav文件
 | 
					
						
							|  |  |  |  | 	f, err := os.Open(musicPath) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		// log.Fatal(err)   Fatal报错直接退出程序
 | 
					
						
							|  |  |  |  | 		log.Println(err) | 
					
						
							|  |  |  |  | 		return err | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	defer f.Close() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 解码wav文件
 | 
					
						
							|  |  |  |  | 	// streamer, format, err := wav.Decode(f)
 | 
					
						
							|  |  |  |  | 	// if err != nil {
 | 
					
						
							|  |  |  |  | 	// 	log.Println(err)
 | 
					
						
							|  |  |  |  | 	// 	return err
 | 
					
						
							|  |  |  |  | 	// }
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 初始化音频驱动
 | 
					
						
							|  |  |  |  | 	// err = speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
 | 
					
						
							|  |  |  |  | 	// if err != nil {
 | 
					
						
							|  |  |  |  | 	// 	log.Println(err)
 | 
					
						
							|  |  |  |  | 	// 	return err
 | 
					
						
							|  |  |  |  | 	// }
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 异步播放音频
 | 
					
						
							|  |  |  |  | 	// go func() {
 | 
					
						
							|  |  |  |  | 	// 	done := make(chan bool)
 | 
					
						
							|  |  |  |  | 	// 	speaker.Play(beep.Seq(streamer, beep.Callback(func() {
 | 
					
						
							|  |  |  |  | 	// 		done <- true
 | 
					
						
							|  |  |  |  | 	// 	})))
 | 
					
						
							|  |  |  |  | 	// 	// 等待音频播放完成
 | 
					
						
							|  |  |  |  | 	// 	<-done
 | 
					
						
							|  |  |  |  | 	// }()
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 播放音频
 | 
					
						
							|  |  |  |  | 	// done := make(chan bool)
 | 
					
						
							|  |  |  |  | 	// speaker.Play(beep.Seq(streamer, beep.Callback(func() {
 | 
					
						
							|  |  |  |  | 	// 	done <- true
 | 
					
						
							|  |  |  |  | 	// })))
 | 
					
						
							|  |  |  |  | 	// fmt.Println("Playing audio...")
 | 
					
						
							|  |  |  |  | 	// // 等待音频播放完成
 | 
					
						
							|  |  |  |  | 	// <-done
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 等待一段时间确保音频播放完毕
 | 
					
						
							|  |  |  |  | 	// time.Sleep(time.Duration(streamer.Len()) / time.Duration(format.SampleRate))
 | 
					
						
							|  |  |  |  | 	// time.Sleep(5 * time.Second)
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // func PlayMusics(musicPath string) error {
 | 
					
						
							|  |  |  |  | // 	// 打开wav文件
 | 
					
						
							|  |  |  |  | // 	f, err := os.Open(musicPath)
 | 
					
						
							|  |  |  |  | // 	if err != nil {
 | 
					
						
							|  |  |  |  | // 		log.Println(err)
 | 
					
						
							|  |  |  |  | // 		return err
 | 
					
						
							|  |  |  |  | // 	}
 | 
					
						
							|  |  |  |  | // 	defer f.Close()
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	// 解码wav文件
 | 
					
						
							|  |  |  |  | // 	streamer, format, err := wav.Decode(f)
 | 
					
						
							|  |  |  |  | // 	if err != nil {
 | 
					
						
							|  |  |  |  | // 		log.Println(err)
 | 
					
						
							|  |  |  |  | // 		return err
 | 
					
						
							|  |  |  |  | // 	}
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	// 初始化音频驱动
 | 
					
						
							|  |  |  |  | // 	err = speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
 | 
					
						
							|  |  |  |  | // 	if err != nil {
 | 
					
						
							|  |  |  |  | // 		log.Println(err)
 | 
					
						
							|  |  |  |  | // 		return err
 | 
					
						
							|  |  |  |  | // 	}
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	// 播放音频
 | 
					
						
							|  |  |  |  | // 	done := make(chan struct{})
 | 
					
						
							|  |  |  |  | // 	// 启动一个新的goroutine来播放音频
 | 
					
						
							|  |  |  |  | // 	go func() {
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 		defer func() {
 | 
					
						
							|  |  |  |  | // 			if err := recover(); err != nil {
 | 
					
						
							|  |  |  |  | // 				log.WithFields(log.Fields{
 | 
					
						
							|  |  |  |  | // 					"function": "PlayMusics",
 | 
					
						
							|  |  |  |  | // 					"error":    err,
 | 
					
						
							|  |  |  |  | // 				}).Error("PlayMusics")
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 				// log.Printf("OpenDevice: %v", err) // 记录错误信息到日志
 | 
					
						
							|  |  |  |  | // 				fmt.Println("PlayMusics:", err) // 打印错误信息
 | 
					
						
							|  |  |  |  | // 			}
 | 
					
						
							|  |  |  |  | // 		}()
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 		defer close(done)
 | 
					
						
							|  |  |  |  | // 		// 使用非阻塞方式播放
 | 
					
						
							|  |  |  |  | // 		speaker.Play(streamer)
 | 
					
						
							|  |  |  |  | // 	}()
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	fmt.Println("Playing audio...")
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	// 等待足够长的时间确保音频播放完毕
 | 
					
						
							|  |  |  |  | // 	time.Sleep(5 * time.Second)
 | 
					
						
							|  |  |  |  | // 	// 等待音频播放完成
 | 
					
						
							|  |  |  |  | // 	<-done
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 	return nil
 | 
					
						
							|  |  |  |  | // }
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // FormatTime 将时间字符串格式化为 HH:MM 格式
 | 
					
						
							|  |  |  |  | func FormatTime(timeStr string) string { | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  |  | 			log.Error("FormatTime:", r) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 按照冒号分割小时和分钟
 | 
					
						
							|  |  |  |  | 	parts := strings.Split(timeStr, ":") | 
					
						
							|  |  |  |  | 	if len(parts) != 2 { | 
					
						
							|  |  |  |  | 		return timeStr // 返回原始字符串如果格式不对
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 将小时和分钟转换为整数
 | 
					
						
							|  |  |  |  | 	hours, err1 := strconv.Atoi(parts[0]) | 
					
						
							|  |  |  |  | 	minutes, err2 := strconv.Atoi(parts[1]) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if err1 != nil || err2 != nil { | 
					
						
							|  |  |  |  | 		return timeStr // 返回原始字符串如果转换失败
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 格式化小时和分钟为两位数字
 | 
					
						
							|  |  |  |  | 	return fmt.Sprintf("%02d:%02d", hours, minutes) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func FormatTimes(now time.Time, format string) string { | 
					
						
							|  |  |  |  | 	// 替换常见的日期时间格式标记
 | 
					
						
							|  |  |  |  | 	format = strings.ReplaceAll(format, "YYYY", "2006") | 
					
						
							|  |  |  |  | 	format = strings.ReplaceAll(format, "YY", "06") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// 特殊处理带中文的月和日
 | 
					
						
							|  |  |  |  | 	if strings.Contains(format, "月") { | 
					
						
							|  |  |  |  | 		format = strings.ReplaceAll(format, "MM", "1") | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		format = strings.ReplaceAll(format, "MM", "01") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if strings.Contains(format, "日") { | 
					
						
							|  |  |  |  | 		format = strings.ReplaceAll(format, "DD", "2") | 
					
						
							|  |  |  |  | 	} else { | 
					
						
							|  |  |  |  | 		format = strings.ReplaceAll(format, "DD", "02") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	format = strings.ReplaceAll(format, "HH", "15") | 
					
						
							|  |  |  |  | 	format = strings.ReplaceAll(format, "mm", "04") | 
					
						
							|  |  |  |  | 	format = strings.ReplaceAll(format, "ss", "05") | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return now.Format(format) | 
					
						
							|  |  |  |  | } |