exprot.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. package service
  2. import (
  3. "archive/zip"
  4. "bp.jydev.jianyu360.cn/BaseService/biService/rpc/pb"
  5. "fmt"
  6. "io"
  7. "log"
  8. "math/rand"
  9. "os"
  10. "path/filepath"
  11. "regexp"
  12. "strings"
  13. "time"
  14. "app.yhyue.com/moapp/jybase/common"
  15. "app.yhyue.com/moapp/jybase/mail"
  16. . "bp.jydev.jianyu360.cn/BaseService/biService/entity"
  17. "github.com/gogf/gf/v2/util/gconv"
  18. "github.com/xuri/excelize/v2"
  19. "github.com/zeromicro/go-zero/core/logx"
  20. )
  21. var (
  22. DateTime = "2006-01-02 15:04:05"
  23. )
  24. type ExportReq struct {
  25. Mail string
  26. Mapping []string
  27. PositionId int64
  28. }
  29. type ExportByDbReq struct {
  30. Token string
  31. Title string
  32. Content string
  33. Mails string
  34. FileName string
  35. Datas []*pb.FilesData
  36. }
  37. var reg1 = regexp.MustCompile("(?i)(insert|delete|update|master|truncate|declare|exec|alter|use)\\s")
  38. var reg2 = regexp.MustCompile("(?i)(select|from)\\s")
  39. // 全量项目导出
  40. func (a *ExportReq) AllProjectExport() {
  41. tableColumn := []string{}
  42. exportKey := []interface{}{}
  43. for _, value := range a.Mapping {
  44. valueArr := strings.Split(value, ":")
  45. tableColumn = append(tableColumn, valueArr[0])
  46. exportKey = append(exportKey, valueArr[1])
  47. }
  48. timeStr := time.Now().Format("20060102150405")
  49. rand.Seed(time.Now().UnixNano())
  50. randomInt := rand.Intn(10000) // 生成0到9999之间的随机整数
  51. timeStr = fmt.Sprintf("%s%s", timeStr, gconv.String(randomInt))
  52. pathArr := export("customer_data_ttzl_project", tableColumn, exportKey, timeStr)
  53. if len(pathArr) > 0 {
  54. folderPath := fmt.Sprintf("%s/%s", ExportDirectory, timeStr)
  55. compressFiles(pathArr, folderPath, timeStr)
  56. pathstr := fmt.Sprintf("%s/%s/%s.zip", ExportUrl, timeStr, timeStr)
  57. state := sendMail("项目", a.Mail, pathstr)
  58. BiService.Insert("export_record", map[string]interface{}{
  59. "positionId": a.PositionId,
  60. "type": "project",
  61. "excelPath": strings.Join(pathArr, ","),
  62. "zipPath": pathstr,
  63. "sendState": state,
  64. "createTime": time.Now().Format(DateTime),
  65. })
  66. }
  67. }
  68. // 全量资讯导出
  69. func (a *ExportReq) AllInfoExport() {
  70. tableColumn := []string{}
  71. exportKey := []interface{}{}
  72. for _, value := range a.Mapping {
  73. valueArr := strings.Split(value, ":")
  74. tableColumn = append(tableColumn, valueArr[0])
  75. exportKey = append(exportKey, valueArr[1])
  76. }
  77. timeStr := time.Now().Format("20060102150405")
  78. rand.Seed(time.Now().UnixNano())
  79. randomInt := rand.Intn(10000) // 生成0到9999之间的随机整数
  80. timeStr = fmt.Sprintf("%s%s", timeStr, gconv.String(randomInt))
  81. pathArr := export("customer_data_ttzl", tableColumn, exportKey, timeStr)
  82. if len(pathArr) > 0 {
  83. folderPath := fmt.Sprintf("%s/%s", ExportDirectory, timeStr)
  84. compressFiles(pathArr, folderPath, timeStr)
  85. pathstr := fmt.Sprintf("%s/%s/%s.zip", ExportUrl, timeStr, timeStr)
  86. state := sendMail("标讯", a.Mail, pathstr)
  87. BiService.Insert("export_record", map[string]interface{}{
  88. "positionId": a.PositionId,
  89. "type": "project",
  90. "excelPath": strings.Join(pathArr, ","),
  91. "zipPath": pathstr,
  92. "sendState": state,
  93. "createTime": time.Now().Format(DateTime),
  94. })
  95. }
  96. }
  97. // 导出开始
  98. func export(table string, tableColumn []string, key []interface{}, timeStr string) []string {
  99. pathArr := []string{}
  100. sqlStr := fmt.Sprintf("SELECT %s FROM %s", strings.Join(tableColumn, ","), table)
  101. fileCounter := 1
  102. writer, file := InirWrite(key)
  103. a := 0
  104. path := ""
  105. BiService.SelectByBath(1, func(l *[]map[string]interface{}) bool {
  106. if a%ExportCount == 0 && a > 0 {
  107. a = 0
  108. //入excel处理
  109. writer, file, path = Warehousing(writer, file, fileCounter, key, ExportDirectory, timeStr)
  110. fileCounter++
  111. pathArr = append(pathArr, path)
  112. }
  113. dataHandle(writer, l, a+1, tableColumn)
  114. a++
  115. return true
  116. }, sqlStr)
  117. if a > 0 && a != ExportCount {
  118. writer, file, path = Warehousing(writer, file, fileCounter, key, ExportDirectory, timeStr)
  119. pathArr = append(pathArr, path)
  120. }
  121. return pathArr
  122. }
  123. // 数据处理
  124. func dataHandle(writer *excelize.StreamWriter, l *[]map[string]interface{}, a int, tableColumn []string) {
  125. for _, value := range *l {
  126. valueArr := []interface{}{}
  127. for _, column := range tableColumn {
  128. valueArr = append(valueArr, gconv.String(value[column]))
  129. }
  130. cell, _ := excelize.CoordinatesToCellName(1, a+1)
  131. writer.SetRow(cell, valueArr)
  132. }
  133. }
  134. // 入excel
  135. func Warehousing(writer *excelize.StreamWriter, file *excelize.File, fileCounter int, key []interface{}, path, timeStr string) (*excelize.StreamWriter, *excelize.File, string) {
  136. writer.Flush()
  137. folderPath := fmt.Sprintf("%s/%s", path, timeStr)
  138. _, err := os.Stat(folderPath)
  139. if os.IsNotExist(err) {
  140. //创建文件夹
  141. err := os.MkdirAll(folderPath, os.ModePerm)
  142. if err != nil {
  143. logx.Info("创建文件夹失败:", err)
  144. }
  145. }
  146. fileName := fmt.Sprintf("%s/output%d.xlsx", folderPath, fileCounter)
  147. err = file.SaveAs(fileName)
  148. if err != nil {
  149. logx.Info(err)
  150. }
  151. writer, file = InirWrite(key)
  152. return writer, file, fileName
  153. }
  154. // excel初始化
  155. func InirWrite(key []interface{}) (*excelize.StreamWriter, *excelize.File) {
  156. //文件初始化
  157. file := excelize.NewFile()
  158. //设置表名
  159. file.SetSheetName("Sheet1", "表1")
  160. //创建流式写入
  161. writer, _ := file.NewStreamWriter("表1")
  162. // 定义每个 Excel 文件的数据列数限制
  163. writer.SetRow("A1", key)
  164. return writer, file
  165. }
  166. func InirWrite1(i int, sheet string, key []interface{}, file *excelize.File) (*excelize.StreamWriter, *excelize.File) {
  167. //文件初始化
  168. if file == nil {
  169. file = excelize.NewFile()
  170. }
  171. if i == 1 {
  172. //设置表名
  173. file.SetSheetName(fmt.Sprintf("Sheet%d", i), sheet)
  174. //创建流式写入
  175. writer, err := file.NewStreamWriter(sheet)
  176. logx.Error(err)
  177. // 定义每个 Excel 文件的数据列数限制
  178. writer.SetRow("A1", key)
  179. return writer, file
  180. } else {
  181. file.NewSheet(sheet)
  182. //创建流式写入
  183. writer, err := file.NewStreamWriter(sheet)
  184. logx.Error(err)
  185. // 定义每个 Excel 文件的数据列数限制
  186. writer.SetRow("A1", key)
  187. return writer, file
  188. }
  189. }
  190. // 发送邮箱
  191. func sendMail(title, target_mail string, path string) bool {
  192. mailStr := "<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <title>铁塔全量%s数据导出</title>\n</head>\n<body>\n<div>\n <p>铁塔全量%s数据已导出成功,导出时间:%s,请点击链接下载数据:<a href=\"%s\">%s</a></p>\n </div>\n</body>"
  193. html := fmt.Sprintf(mailStr, title, title, time.Now().Format(DateTime), path, path)
  194. fool := false
  195. for k, v := range GmailAuth {
  196. fool := mail.GSendMail("剑鱼标讯", target_mail, "", "", fmt.Sprintf("铁塔全量%s数据导出", title), html, "", "", v)
  197. if fool {
  198. logx.Info(target_mail, fmt.Sprintf("使用%s发送邮件成功", v.User))
  199. break
  200. }
  201. if k < len(GmailAuth)-1 {
  202. logx.Info(target_mail, fmt.Sprintf("使用%s发送邮件失败!3s后使用其他邮箱尝试", v.User))
  203. } else {
  204. logx.Info(target_mail, fmt.Sprintf("使用%s发送邮件失败!", v.User))
  205. }
  206. time.Sleep(time.Second * 3)
  207. }
  208. return fool
  209. }
  210. // 文件压缩
  211. func compressFiles(filePattern []string, path, timeStr string) {
  212. _, err := os.Stat(path)
  213. if os.IsNotExist(err) {
  214. //创建文件夹
  215. err := os.MkdirAll(path, os.ModePerm)
  216. if err != nil {
  217. logx.Info("创建文件夹失败:", err)
  218. }
  219. }
  220. zipFilename := fmt.Sprintf("%s/%s.zip", path, timeStr)
  221. // 创建 ZIP 文件
  222. zipFile, err := os.Create(zipFilename)
  223. if err != nil {
  224. log.Fatal(err)
  225. }
  226. defer zipFile.Close()
  227. // 创建 ZIP Writer
  228. zipWriter := zip.NewWriter(zipFile)
  229. defer zipWriter.Close()
  230. // 遍历文件列表
  231. for _, file := range filePattern {
  232. // 打开文件
  233. f, err := os.Open(file)
  234. if err != nil {
  235. log.Fatal(err)
  236. }
  237. defer f.Close()
  238. // 获取文件信息
  239. _, err = f.Stat()
  240. if err != nil {
  241. log.Fatal(err)
  242. }
  243. //文件名切割
  244. nameArr := strings.Split(file, "/")
  245. name := nameArr[len(nameArr)-1]
  246. name = fmt.Sprintf("%s/%s", timeStr, name)
  247. // 创建 ZIP 内部文件
  248. zipFile, err := zipWriter.Create(name)
  249. if err != nil {
  250. log.Fatal(err)
  251. }
  252. // 将文件内容复制到 ZIP 文件中
  253. _, err = io.Copy(zipFile, f)
  254. if err != nil {
  255. log.Fatal(err)
  256. }
  257. }
  258. // 打印压缩文件路径
  259. absPath, err := filepath.Abs(zipFilename)
  260. if err != nil {
  261. log.Fatal(err)
  262. }
  263. log.Printf("Files compressed to: %s", absPath)
  264. //return fmt.Sprintf("%s/%s/%s.zip", url, timeStr, timeStr)
  265. //return fmt.Sprintf("%s/%s/%s.zip", url, timeStr, timeStr)
  266. }
  267. // 数据导出(通用)
  268. func (e *ExportByDbReq) ExportDataByDb() []byte {
  269. stype := "public"
  270. var writer *excelize.StreamWriter
  271. var file *excelize.File
  272. timeStr := time.Now().Format("20060102150405")
  273. rand.Seed(time.Now().UnixNano())
  274. randomInt := rand.Intn(10000) // 生成0到9999之间的随机整数
  275. timeStr = fmt.Sprintf("%s%s", timeStr, gconv.String(randomInt))
  276. path1 := fmt.Sprintf("%s/%s", ComFileDir, stype)
  277. var pathArr []string
  278. for i, data := range e.Datas {
  279. key := hName(data.Sql)
  280. sheet := data.SheetName
  281. writer, file = InirWrite1(i+1, sheet, key, file)
  282. exportA(data.Sql, key, writer)
  283. }
  284. fpath := ""
  285. writer, file, fpath = WarehousingA(writer, file, path1, timeStr, e.FileName)
  286. pathArr = append(pathArr, fpath)
  287. if len(pathArr) > 0 {
  288. var files []string
  289. for _, s := range pathArr {
  290. ss := strings.Split(s, "/")
  291. files = append(files, fmt.Sprintf("%s/%s/%s/%s.xlsx", ComFileUrl, stype, timeStr, ss[len(ss)-1]))
  292. }
  293. state := sendMailA(e.Title, e.Mails, e.Content, strings.Join(files, ","))
  294. BiService.Insert("export_record", map[string]interface{}{
  295. "positionId": "0",
  296. "type": stype,
  297. "excelPath": strings.Join(pathArr, ","),
  298. "zipPath": "",
  299. "sendState": state,
  300. "createTime": time.Now().Format(DateTime),
  301. })
  302. return gconv.Bytes(map[string]interface{}{"status": 1, "msg": "导出数据成功"})
  303. }
  304. return gconv.Bytes(map[string]interface{}{"status": -1, "msg": "导出数据失败,未查询到数据"})
  305. }
  306. // 表头
  307. func hName(sql string) []interface{} {
  308. if reg1.MatchString(sql) && !reg2.MatchString(sql) {
  309. return []interface{}{}
  310. }
  311. var key []interface{}
  312. s := strings.Split(strings.ToLower(sql), "from")
  313. keystr := strings.ReplaceAll(s[0], "select", "")
  314. keystr = strings.ReplaceAll(keystr, " ", "")
  315. for _, s1 := range strings.Split(keystr, ",") {
  316. if strings.Contains(s1, "as") {
  317. a1 := strings.Split(s1, "as")
  318. l1 := len(a1)
  319. chiReg := regexp.MustCompile("[^\u4e00-\u9fa5]")
  320. if !chiReg.MatchString(a1[l1-1]) {
  321. key = append(key, a1[l1-1])
  322. }
  323. }
  324. }
  325. if key != nil {
  326. return key
  327. } else {
  328. return []interface{}{}
  329. }
  330. }
  331. // 导出开始
  332. func exportA(sql string, key []interface{}, writer *excelize.StreamWriter) {
  333. a := 0
  334. JyBiTidb.SelectByBath(1, func(l *[]map[string]interface{}) bool {
  335. dataHandle(writer, l, a+1, common.ObjArrToStringArr(key))
  336. a++
  337. return true
  338. }, sql)
  339. }
  340. func WarehousingA(writer *excelize.StreamWriter, file *excelize.File, path, timeStr, fileName string) (*excelize.StreamWriter, *excelize.File, string) {
  341. writer.Flush()
  342. folderPath := fmt.Sprintf("%s/%s", path, timeStr)
  343. _, err := os.Stat(folderPath)
  344. if os.IsNotExist(err) {
  345. //创建文件夹
  346. err := os.MkdirAll(folderPath, os.ModePerm)
  347. if err != nil {
  348. logx.Info("创建文件夹失败:", err)
  349. }
  350. }
  351. f := fmt.Sprintf("%s/%s.xlsx", folderPath, fileName)
  352. err = file.SaveAs(f)
  353. if err != nil {
  354. logx.Info(err)
  355. }
  356. return writer, file, fileName
  357. }
  358. func sendMailA(title, target_mail, content string, path string) bool {
  359. html := strings.ReplaceAll(content, "#downLoadUrl#", path)
  360. fool := false
  361. for k, v := range GmailAuth {
  362. fool := mail.GSendMail("剑鱼标讯", target_mail, "", "", fmt.Sprintf("%s数据导出", title), html, "", "", v)
  363. if fool {
  364. logx.Info(target_mail, fmt.Sprintf("使用%s发送邮件成功", v.User))
  365. break
  366. }
  367. if k < len(GmailAuth)-1 {
  368. logx.Info(target_mail, fmt.Sprintf("使用%s发送邮件失败!3s后使用其他邮箱尝试", v.User))
  369. } else {
  370. logx.Info(target_mail, fmt.Sprintf("使用%s发送邮件失败!", v.User))
  371. }
  372. time.Sleep(time.Second * 3)
  373. }
  374. return fool
  375. }