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
|
|
}
|