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

  1. package common
  2. import (
  3. "container/list"
  4. "errors"
  5. "fmt"
  6. "github.com/lianggx6/goutf16"
  7. "io/ioutil"
  8. "leit.com/leit_seat_aps/mysmtp"
  9. "log"
  10. "math/rand"
  11. "os"
  12. "os/exec"
  13. "path/filepath"
  14. "reflect"
  15. "regexp"
  16. "sort"
  17. "strconv"
  18. "strings"
  19. "syscall"
  20. "time"
  21. "unsafe"
  22. )
  23. type HWND uintptr
  24. const (
  25. ERROR_FILE_NOT_FOUND = 2
  26. ERROR_PATH_NOT_FOUND = 3
  27. ERROR_BAD_FORMAT = 11
  28. )
  29. const (
  30. SE_ERR_ACCESSDENIED = 5
  31. SE_ERR_OOM = 8
  32. SE_ERR_DLLNOTFOUND = 32
  33. SE_ERR_SHARE = 26
  34. SE_ERR_ASSOCINCOMPLETE = 27
  35. SE_ERR_DDETIMEOUT = 28
  36. SE_ERR_DDEFAIL = 29
  37. SE_ERR_DDEBUSY = 30
  38. SE_ERR_NOASSOC = 31
  39. )
  40. var (
  41. modshell32 = syscall.NewLazyDLL("shell32.dll")
  42. procShellExecute = modshell32.NewProc("ShellExecuteW")
  43. )
  44. // 将结构体内所有string类型字段去除首位空格
  45. // sp为结构体指针, s为结构体值
  46. func TrimStruct(sp interface{}, s interface{}) {
  47. // 判断类型是否为struct
  48. av := reflect.ValueOf(sp)
  49. avv := reflect.ValueOf(s)
  50. at := reflect.TypeOf(s)
  51. // 简单判断下
  52. if at.Kind() != reflect.Struct {
  53. log.Printf("s must be a struct")
  54. return
  55. }
  56. av = reflect.ValueOf(av.Interface())
  57. for i := 0; i < avv.NumField(); i++ {
  58. if at.Field(i).Type.Name() == "string" {
  59. f := av.Elem().Field(i)
  60. val := strings.TrimSpace(avv.Field(i).String())
  61. f.Set(reflect.ValueOf(val))
  62. }
  63. }
  64. return
  65. }
  66. // 将给定的整数值转换成给定长度的字符串,不足长度的在前面补足0
  67. func ConvInt2FormatString(input, ilen int) (retstring string) {
  68. var igap int
  69. if len(string(input)) >= ilen {
  70. retstring = string(input)
  71. } else {
  72. igap = ilen - len(strconv.Itoa(input))
  73. if igap > 0 {
  74. retstring = strings.Repeat("0", igap) + strconv.Itoa(input)
  75. } else {
  76. retstring = strconv.Itoa(input)
  77. }
  78. }
  79. return
  80. }
  81. // 基于文件信息中的修改时间按先后排序
  82. func SortByTime(pl []os.FileInfo) []os.FileInfo {
  83. sort.Slice(pl, func(i, j int) bool {
  84. flag := false
  85. if pl[i].ModTime().Before(pl[j].ModTime()) {
  86. flag = true
  87. } else if pl[i].ModTime().Equal(pl[j].ModTime()) {
  88. if pl[i].Name() < pl[j].Name() {
  89. flag = true
  90. }
  91. }
  92. return flag
  93. })
  94. return pl
  95. }
  96. // 将某目录下的文件按照修改时间先后依次列出
  97. func listAll(path string, curHier int) {
  98. readerInfos, err := ioutil.ReadDir(path)
  99. if err != nil {
  100. fmt.Println(err)
  101. return
  102. }
  103. readerInfos1 := SortByTime(readerInfos)
  104. for _, info := range readerInfos1 {
  105. if info.IsDir() {
  106. for tmpheir := curHier; tmpheir > 0; tmpheir-- {
  107. fmt.Printf("|\t")
  108. }
  109. fmt.Println(info.Name(), "\\")
  110. listAll(path+"\\"+info.Name(), curHier+1)
  111. } else {
  112. for tmpheir := curHier; tmpheir > 0; tmpheir-- {
  113. fmt.Printf("|\t")
  114. }
  115. fmt.Println(info.Name(), " ", info.ModTime())
  116. }
  117. }
  118. }
  119. func RemoveListAllBeforeItem(lst *list.List, delNode *list.Element, delItem bool) (err error) {
  120. var (
  121. e, el, prev, p *list.Element
  122. )
  123. // 删除litem之前所有的节点
  124. for e = lst.Front(); e != nil; e = e.Next() {
  125. if delNode == e {
  126. prev = e.Prev()
  127. if delItem {
  128. lst.Remove(e)
  129. }
  130. for el = prev; el != nil; el = p {
  131. p = el.Prev()
  132. lst.Remove(el)
  133. }
  134. break
  135. }
  136. }
  137. return
  138. }
  139. func RemoveListAllAfterItem(lst *list.List, delNode *list.Element, delItem bool) (err error) {
  140. var (
  141. e, el, next, n *list.Element
  142. )
  143. // 删除litem之前所有的节点
  144. for e = lst.Front(); e != nil; e = e.Next() {
  145. if delNode == e {
  146. next = e.Next()
  147. if delItem {
  148. lst.Remove(e)
  149. }
  150. for el = next; el != nil; el = n {
  151. n = el.Next()
  152. lst.Remove(el)
  153. }
  154. break
  155. }
  156. }
  157. return
  158. }
  159. func StructToMap(data []interface{}) map[string]string {
  160. keyMap := make(map[string]string)
  161. for _, v := range data {
  162. value := reflect.ValueOf(v)
  163. typeInfo := reflect.TypeOf(v)
  164. kd := value.Kind() //获取到a对应的类别
  165. if kd != reflect.Struct {
  166. continue
  167. }
  168. count := value.NumField()
  169. for i := 0; i < count; i++ {
  170. val := value.Field(i).Interface()
  171. key := typeInfo.Field(i).Tag.Get("json")
  172. //fmt.Println(key,":",val)
  173. keyMap[key] = ValueToString(val, "")
  174. }
  175. }
  176. return keyMap
  177. }
  178. func GetCurrentDir() string {
  179. file, err := exec.LookPath(os.Args[0])
  180. if err != nil {
  181. c, _ := os.Getwd()
  182. return c
  183. }
  184. return strings.Replace(filepath.Dir(file), "\\", "/", -1)
  185. }
  186. func GetAbsolutePath(path string) string {
  187. p := GetAbsolutePathNoFilter(path)
  188. p = strings.Replace(p, "\\", "/", -1) // 统一使用/
  189. for {
  190. a := strings.Index(p, "//")
  191. if a == -1 {
  192. break
  193. }
  194. p = strings.Replace(p, "//", "/", -1)
  195. }
  196. return p
  197. }
  198. func GetAbsolutePathNoFilter(path string) string {
  199. if strings.Index(path, "file:/") == 0 {
  200. path = path[5:]
  201. mpos := strings.Index(path, ":")
  202. if mpos >= 0 {
  203. //去除开头斜杠, 如: ///C:/test
  204. for {
  205. if len(path) > 0 && (path[0] == '/' || path[0] == '\\') {
  206. path = path[1:]
  207. } else {
  208. break
  209. }
  210. }
  211. return (path)
  212. }
  213. for {
  214. if len(path) > 1 && (path[0] == '/' || path[0] == '\\') && (path[1] == '/' || path[1] == '\\') {
  215. path = path[1:]
  216. } else {
  217. break
  218. }
  219. }
  220. path, _ = filepath.Abs(path)
  221. return (path)
  222. } else if strings.Index(path, "./") == 0 || strings.Index(path, ".\\") == 0 {
  223. r, _ := filepath.Abs(GetCurrentDir() + path[1:])
  224. return (r)
  225. }
  226. r, _ := filepath.Abs(path)
  227. return (r)
  228. }
  229. func GetDir(path string) string {
  230. if strings.Index(path, "./") == 0 || strings.Index(path, ".\\") == 0 {
  231. return filepath.ToSlash(filepath.Dir(GetCurrentDir() + path[1:]))
  232. }
  233. return filepath.ToSlash(filepath.Dir(path))
  234. }
  235. func EnsureDir(dir string) string {
  236. fullDir := GetAbsolutePath(dir)
  237. if IsExists(fullDir) {
  238. return fullDir
  239. }
  240. os.MkdirAll(fullDir, 777)
  241. return fullDir
  242. }
  243. func EnsureFilePath(filePath string) string {
  244. filePath = GetAbsolutePath(filePath)
  245. EnsureDir(GetDir(filePath))
  246. return filePath
  247. }
  248. func IsExists(path string) bool {
  249. if path == "" {
  250. return false
  251. }
  252. _, err := os.Stat(path)
  253. if err != nil && os.IsNotExist(err) {
  254. return false
  255. }
  256. return true
  257. }
  258. func Max(vals ...int) int {
  259. var max int
  260. for _, val := range vals {
  261. if val > max {
  262. max = val
  263. }
  264. }
  265. return max
  266. }
  267. func Min(vals ...int) int {
  268. var min int
  269. for _, val := range vals {
  270. if min == 0 || val <= min {
  271. min = val
  272. }
  273. }
  274. return min
  275. }
  276. func UintSliceTo256Uint(us []uint16) (res [256]uint16) {
  277. var i int
  278. for i = 0; i < len(us); i++ {
  279. res[i] = us[i]
  280. }
  281. return res
  282. }
  283. // 设置默认打印机
  284. func SetDefaultPrinter(printerName string, orientation int) error {
  285. var (
  286. dll = syscall.MustLoadDLL("winspool.drv")
  287. setDefaultPrinter = dll.MustFindProc("SetDefaultPrinterW")
  288. p []uint16
  289. pn [256]uint16
  290. )
  291. p = goutf16.EncodeStringToUTF16(printerName)
  292. pn = UintSliceTo256Uint(p)
  293. ret, _, msg := setDefaultPrinter.Call(uintptr(unsafe.Pointer(&pn)))
  294. if ret == 0 {
  295. return msg
  296. }
  297. return nil
  298. }
  299. func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
  300. var op, param, directory uintptr
  301. if len(lpOperation) != 0 {
  302. op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
  303. }
  304. if len(lpParameters) != 0 {
  305. param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
  306. }
  307. if len(lpDirectory) != 0 {
  308. directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
  309. }
  310. ret, _, _ := procShellExecute.Call(
  311. uintptr(hwnd),
  312. op,
  313. uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
  314. param,
  315. directory,
  316. uintptr(nShowCmd))
  317. errorMsg := ""
  318. if ret != 0 && ret <= 32 {
  319. switch int(ret) {
  320. case ERROR_FILE_NOT_FOUND:
  321. errorMsg = "The specified file was not found."
  322. case ERROR_PATH_NOT_FOUND:
  323. errorMsg = "The specified path was not found."
  324. case ERROR_BAD_FORMAT:
  325. errorMsg = "The .exe file is invalid (non-Win32 .exe or error in .exe image)."
  326. case SE_ERR_ACCESSDENIED:
  327. errorMsg = "The operating system denied access to the specified file."
  328. case SE_ERR_ASSOCINCOMPLETE:
  329. errorMsg = "The file name association is incomplete or invalid."
  330. case SE_ERR_DDEBUSY:
  331. errorMsg = "The DDE transaction could not be completed because other DDE transactions were being processed."
  332. case SE_ERR_DDEFAIL:
  333. errorMsg = "The DDE transaction failed."
  334. case SE_ERR_DDETIMEOUT:
  335. errorMsg = "The DDE transaction could not be completed because the request timed out."
  336. case SE_ERR_DLLNOTFOUND:
  337. errorMsg = "The specified DLL was not found."
  338. case SE_ERR_NOASSOC:
  339. 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."
  340. case SE_ERR_OOM:
  341. errorMsg = "There was not enough memory to complete the operation."
  342. case SE_ERR_SHARE:
  343. errorMsg = "A sharing violation occurred."
  344. default:
  345. errorMsg = fmt.Sprintf("Unknown error occurred with error code %v", ret)
  346. }
  347. } else {
  348. return nil
  349. }
  350. return errors.New(errorMsg)
  351. }
  352. // 将Excel的字母定位转换成数字定位值
  353. func GetExcelCellIntPos(pos string) (row, col int, err error) {
  354. var (
  355. chareg, numreg *regexp.Regexp
  356. cha, num [][]string
  357. i int
  358. uc []rune
  359. rowstr string
  360. )
  361. chareg = regexp.MustCompile("[a-zA-Z]")
  362. numreg = regexp.MustCompile("[0-9]")
  363. cha = chareg.FindAllStringSubmatch(pos, -1)
  364. num = numreg.FindAllStringSubmatch(pos, -1)
  365. // 获取字符的列值
  366. col = 0
  367. for i = 0; i < len(cha); i++ {
  368. uc = []rune(strings.ToUpper(cha[i][0]))
  369. col = col + i*26 + (int(uc[0]) - 65)
  370. }
  371. // 获取行值
  372. for i = 0; i < len(num); i++ {
  373. rowstr = rowstr + num[i][0]
  374. }
  375. row, _ = strconv.Atoi(rowstr)
  376. return row - 1, col, nil
  377. }
  378. // 将Excel的字母定位转换成数字定位值
  379. func AddExcelColLen(colname string, ilen int) (retcol string) {
  380. var (
  381. chareg *regexp.Regexp
  382. cha [][]string
  383. i, col, iloop, imod int
  384. uc []rune
  385. )
  386. chareg = regexp.MustCompile("[a-zA-Z]")
  387. cha = chareg.FindAllStringSubmatch(colname, -1)
  388. // 获取字符的列值
  389. col = 0
  390. for i = 0; i < len(cha); i++ {
  391. uc = []rune(strings.ToUpper(cha[i][0]))
  392. col = col + i*26 + (int(uc[0]) - 65)
  393. }
  394. col = col + ilen
  395. // 将增加后的数值再转换成字符
  396. iloop = col / 26
  397. imod = col % 26
  398. retcol = strings.Repeat("A", iloop)
  399. retcol = retcol + string('A'+imod)
  400. return retcol
  401. }
  402. //windows环境下获取绝对路径
  403. func GetCurrentPath(dir string) (string, error) {
  404. file, err := exec.LookPath(os.Args[0])
  405. if err != nil {
  406. return "", err
  407. }
  408. path, err := filepath.Abs(file)
  409. if err != nil {
  410. return "", err
  411. }
  412. i := strings.LastIndex(path, "/")
  413. if i < 0 {
  414. i = strings.LastIndex(path, "\\")
  415. }
  416. if i < 0 {
  417. return "", errors.New(`error: Can't find "/" or "\".`)
  418. }
  419. pathdir := string(path[0 : i+1])
  420. if len(dir) > 0 {
  421. dir = strings.Replace(dir, "/", "\\", -1)
  422. return filepath.Join(pathdir, dir), nil
  423. }
  424. return string(path[0 : i+1]), nil
  425. }
  426. func CreateCaptcha() string {
  427. return fmt.Sprintf("%02v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100))
  428. }
  429. func CreateCaptchaFive() string {
  430. return fmt.Sprintf("%05v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(100000))
  431. }
  432. func CreateCaptchaFour() string {
  433. return fmt.Sprintf("%04v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(10000))
  434. }
  435. /*!
  436. username 发送者邮件
  437. password 授权码
  438. host 主机地址 smtp.qq.com:587 smtp.qq.com:25
  439. to 接收邮箱 多个接收邮箱使用 ; 隔开
  440. name 发送人名称
  441. subject 发送主题
  442. body 发送内容
  443. mailType 发送邮件内容类型
  444. */
  445. func SendMail(username, password, host, to, name, subject, body, mailType string) error {
  446. hp := strings.Split(host, ":")
  447. auth := mysmtp.LoginAuth(username, password, hp[0])
  448. var contentType string
  449. if mailType == "html" {
  450. contentType = "Content-Type: text/" + mailType + "; charset=UTF-8"
  451. } else {
  452. contentType = "Content-Type: text/plain" + "; charset=UTF-8"
  453. }
  454. msg := []byte("To: " + to + "\r\nFrom: " + name + "<" + username + ">\r\nSubject: " + subject + "\r\n" + contentType + "\r\n\r\n" + body)
  455. sendTo := strings.Split(to, ";")
  456. err := mysmtp.SendMail(host, auth, username, sendTo, msg)
  457. return err
  458. }