SJA APS后端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

507 lines
12 KiB

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
}