package common import ( "container/list" "errors" "fmt" "github.com/lianggx6/goutf16" "io/ioutil" "leit.com/leit_seat_aps/mysmtp" "log" "math/rand" "os" "os/exec" "path/filepath" "reflect" "regexp" "sort" "strconv" "strings" "syscall" "time" "unsafe" ) type HWND uintptr const ( ERROR_FILE_NOT_FOUND = 2 ERROR_PATH_NOT_FOUND = 3 ERROR_BAD_FORMAT = 11 ) const ( SE_ERR_ACCESSDENIED = 5 SE_ERR_OOM = 8 SE_ERR_DLLNOTFOUND = 32 SE_ERR_SHARE = 26 SE_ERR_ASSOCINCOMPLETE = 27 SE_ERR_DDETIMEOUT = 28 SE_ERR_DDEFAIL = 29 SE_ERR_DDEBUSY = 30 SE_ERR_NOASSOC = 31 ) var ( modshell32 = syscall.NewLazyDLL("shell32.dll") procShellExecute = modshell32.NewProc("ShellExecuteW") ) // 将结构体内所有string类型字段去除首位空格 // sp为结构体指针, s为结构体值 func TrimStruct(sp interface{}, s interface{}) { // 判断类型是否为struct av := reflect.ValueOf(sp) avv := reflect.ValueOf(s) at := reflect.TypeOf(s) // 简单判断下 if at.Kind() != reflect.Struct { log.Printf("s must be a struct") return } av = reflect.ValueOf(av.Interface()) for i := 0; i < avv.NumField(); i++ { if at.Field(i).Type.Name() == "string" { f := av.Elem().Field(i) val := strings.TrimSpace(avv.Field(i).String()) f.Set(reflect.ValueOf(val)) } } return } // 将给定的整数值转换成给定长度的字符串,不足长度的在前面补足0 func ConvInt2FormatString(input, ilen int) (retstring string) { var igap int if len(string(input)) >= ilen { retstring = string(input) } else { igap = ilen - len(strconv.Itoa(input)) if igap > 0 { retstring = strings.Repeat("0", igap) + strconv.Itoa(input) } else { retstring = strconv.Itoa(input) } } return } // 基于文件信息中的修改时间按先后排序 func SortByTime(pl []os.FileInfo) []os.FileInfo { sort.Slice(pl, func(i, j int) bool { flag := false if pl[i].ModTime().Before(pl[j].ModTime()) { flag = true } else if pl[i].ModTime().Equal(pl[j].ModTime()) { if pl[i].Name() < pl[j].Name() { flag = true } } return flag }) return pl } // 将某目录下的文件按照修改时间先后依次列出 func listAll(path string, curHier int) { readerInfos, err := ioutil.ReadDir(path) if err != nil { fmt.Println(err) return } readerInfos1 := SortByTime(readerInfos) for _, info := range readerInfos1 { if info.IsDir() { for tmpheir := curHier; tmpheir > 0; tmpheir-- { fmt.Printf("|\t") } fmt.Println(info.Name(), "\\") listAll(path+"\\"+info.Name(), curHier+1) } else { for tmpheir := curHier; tmpheir > 0; tmpheir-- { fmt.Printf("|\t") } fmt.Println(info.Name(), " ", info.ModTime()) } } } func RemoveListAllBeforeItem(lst *list.List, delNode *list.Element, delItem bool) (err error) { var ( e, el, prev, p *list.Element ) // 删除litem之前所有的节点 for e = lst.Front(); e != nil; e = e.Next() { if delNode == e { prev = e.Prev() if delItem { lst.Remove(e) } for el = prev; el != nil; el = p { p = el.Prev() lst.Remove(el) } break } } return } func RemoveListAllAfterItem(lst *list.List, delNode *list.Element, delItem bool) (err error) { var ( e, el, next, n *list.Element ) // 删除litem之前所有的节点 for e = lst.Front(); e != nil; e = e.Next() { if delNode == e { next = e.Next() if delItem { lst.Remove(e) } for el = next; el != nil; el = n { n = el.Next() lst.Remove(el) } break } } return } func StructToMap(data []interface{}) map[string]string { keyMap := make(map[string]string) for _, v := range data { value := reflect.ValueOf(v) typeInfo := reflect.TypeOf(v) kd := value.Kind() //获取到a对应的类别 if kd != reflect.Struct { continue } count := value.NumField() for i := 0; i < count; i++ { val := value.Field(i).Interface() key := typeInfo.Field(i).Tag.Get("json") //fmt.Println(key,":",val) keyMap[key] = ValueToString(val, "") } } return keyMap } func GetCurrentDir() string { file, err := exec.LookPath(os.Args[0]) if err != nil { c, _ := os.Getwd() return c } return strings.Replace(filepath.Dir(file), "\\", "/", -1) } func GetAbsolutePath(path string) string { p := GetAbsolutePathNoFilter(path) p = strings.Replace(p, "\\", "/", -1) // 统一使用/ for { a := strings.Index(p, "//") if a == -1 { break } p = strings.Replace(p, "//", "/", -1) } return p } func GetAbsolutePathNoFilter(path string) string { if strings.Index(path, "file:/") == 0 { path = path[5:] mpos := strings.Index(path, ":") if mpos >= 0 { //去除开头斜杠, 如: ///C:/test for { if len(path) > 0 && (path[0] == '/' || path[0] == '\\') { path = path[1:] } else { break } } return (path) } for { if len(path) > 1 && (path[0] == '/' || path[0] == '\\') && (path[1] == '/' || path[1] == '\\') { path = path[1:] } else { break } } path, _ = filepath.Abs(path) return (path) } else if strings.Index(path, "./") == 0 || strings.Index(path, ".\\") == 0 { r, _ := filepath.Abs(GetCurrentDir() + path[1:]) return (r) } r, _ := filepath.Abs(path) return (r) } func GetDir(path string) string { if strings.Index(path, "./") == 0 || strings.Index(path, ".\\") == 0 { return filepath.ToSlash(filepath.Dir(GetCurrentDir() + path[1:])) } return filepath.ToSlash(filepath.Dir(path)) } func EnsureDir(dir string) string { fullDir := GetAbsolutePath(dir) if IsExists(fullDir) { return fullDir } os.MkdirAll(fullDir, 777) return fullDir } func EnsureFilePath(filePath string) string { filePath = GetAbsolutePath(filePath) EnsureDir(GetDir(filePath)) return filePath } func IsExists(path string) bool { if path == "" { return false } _, err := os.Stat(path) if err != nil && os.IsNotExist(err) { return false } return true } func Max(vals ...int) int { var max int for _, val := range vals { if val > max { max = val } } return max } func Min(vals ...int) int { var min int for _, val := range vals { if min == 0 || val <= min { min = val } } return min } func UintSliceTo256Uint(us []uint16) (res [256]uint16) { var i int for i = 0; i < len(us); i++ { res[i] = us[i] } return res } // 设置默认打印机 func SetDefaultPrinter(printerName string, orientation int) error { var ( dll = syscall.MustLoadDLL("winspool.drv") setDefaultPrinter = dll.MustFindProc("SetDefaultPrinterW") p []uint16 pn [256]uint16 ) p = goutf16.EncodeStringToUTF16(printerName) pn = UintSliceTo256Uint(p) ret, _, msg := setDefaultPrinter.Call(uintptr(unsafe.Pointer(&pn))) if ret == 0 { return msg } return nil } func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error { var op, param, directory uintptr if len(lpOperation) != 0 { op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation))) } if len(lpParameters) != 0 { param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters))) } if len(lpDirectory) != 0 { directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory))) } ret, _, _ := procShellExecute.Call( uintptr(hwnd), op, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))), param, directory, uintptr(nShowCmd)) errorMsg := "" if ret != 0 && ret <= 32 { switch int(ret) { case ERROR_FILE_NOT_FOUND: errorMsg = "The specified file was not found." case ERROR_PATH_NOT_FOUND: errorMsg = "The specified path was not found." case ERROR_BAD_FORMAT: errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)." case SE_ERR_ACCESSDENIED: errorMsg = "The operating system denied access to the specified file." case SE_ERR_ASSOCINCOMPLETE: errorMsg = "The file name association is incomplete or invalid." case SE_ERR_DDEBUSY: errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed." case SE_ERR_DDEFAIL: errorMsg = "The DDE transaction failed." case SE_ERR_DDETIMEOUT: errorMsg = "The DDE transaction could not be completed because the request timed out." case SE_ERR_DLLNOTFOUND: errorMsg = "The specified DLL was not found." case SE_ERR_NOASSOC: errorMsg = "There is no application associated with the given file name extension. This error will also be returned if you attempt to print a file that is not printable." case SE_ERR_OOM: errorMsg = "There was not enough memory to complete the operation." case SE_ERR_SHARE: errorMsg = "A sharing violation occurred." default: errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret) } } else { return nil } return errors.New(errorMsg) } // 将Excel的字母定位转换成数字定位值 func GetExcelCellIntPos(pos string) (row, col int, err error) { var ( chareg, numreg *regexp.Regexp cha, num [][]string i int uc []rune rowstr string ) chareg = regexp.MustCompile("[a-zA-Z]") numreg = regexp.MustCompile("[0-9]") cha = chareg.FindAllStringSubmatch(pos, -1) num = numreg.FindAllStringSubmatch(pos, -1) // 获取字符的列值 col = 0 for i = 0; i < len(cha); i++ { uc = []rune(strings.ToUpper(cha[i][0])) col = col + i*26 + (int(uc[0]) - 65) } // 获取行值 for i = 0; i < len(num); i++ { rowstr = rowstr + num[i][0] } row, _ = strconv.Atoi(rowstr) return row - 1, col, nil } // 将Excel的字母定位转换成数字定位值 func AddExcelColLen(colname string, ilen int) (retcol string) { var ( chareg *regexp.Regexp cha [][]string i, col, iloop, imod int uc []rune ) chareg = regexp.MustCompile("[a-zA-Z]") cha = chareg.FindAllStringSubmatch(colname, -1) // 获取字符的列值 col = 0 for i = 0; i < len(cha); i++ { uc = []rune(strings.ToUpper(cha[i][0])) col = col + i*26 + (int(uc[0]) - 65) } col = col + ilen // 将增加后的数值再转换成字符 iloop = col / 26 imod = col % 26 retcol = strings.Repeat("A", iloop) retcol = retcol + string('A'+imod) return retcol } //windows环境下获取绝对路径 func GetCurrentPath(dir string) (string, error) { file, err := exec.LookPath(os.Args[0]) if err != nil { return "", err } path, err := filepath.Abs(file) if err != nil { return "", err } i := strings.LastIndex(path, "/") if i < 0 { i = strings.LastIndex(path, "\\") } if i < 0 { return "", errors.New(`error: Can't find "/" or "\".`) } pathdir := string(path[0 : i+1]) if len(dir) > 0 { dir = strings.Replace(dir, "/", "\\", -1) return filepath.Join(pathdir, dir), nil } return string(path[0 : i+1]), nil } func CreateCaptcha() string { return fmt.Sprintf("%02v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100)) } func CreateCaptchaFive() string { return fmt.Sprintf("%05v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100000)) } func CreateCaptchaFour() string { return fmt.Sprintf("%04v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(10000)) } /*! username 发送者邮件 password 授权码 host 主机地址 smtp.qq.com:587 或 smtp.qq.com:25 to 接收邮箱 多个接收邮箱使用 ; 隔开 name 发送人名称 subject 发送主题 body 发送内容 mailType 发送邮件内容类型 */ func SendMail(username, password, host, to, name, subject, body, mailType string) error { hp := strings.Split(host, ":") auth := mysmtp.LoginAuth(username, password, hp[0]) var contentType string if mailType == "html" { contentType = "Content-Type: text/" + mailType + "; charset=UTF-8" } else { contentType = "Content-Type: text/plain" + "; charset=UTF-8" } msg := []byte("To: " + to + "\r\nFrom: " + name + "<" + username + ">\r\nSubject: " + subject + "\r\n" + contentType + "\r\n\r\n" + body) sendTo := strings.Split(to, ";") err := mysmtp.SendMail(host, auth, username, sendTo, msg) return err }