export_stat.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. package services
  2. import (
  3. "errors"
  4. "eta/eta_api/models"
  5. "eta/eta_api/models/roadshow"
  6. "eta/eta_api/utils"
  7. "fmt"
  8. "github.com/tealeg/xlsx"
  9. "sort"
  10. "time"
  11. )
  12. // exportReportStat
  13. // @Description: 导出报告统计数据
  14. func exportReportStat() {
  15. startDate := `2025-01-01 00:00:00`
  16. endDate := `2025-07-01 00:00:00`
  17. // 特殊的报告分类id列表(本身是章节报告,可是却要统计在普通报告里面)
  18. otherReportClassifyIdList := []int{185, 91}
  19. hongGuanReportClassifyId := []int{91} // 宏观报告,需要按照二级分类来分组
  20. onlyReportClassifyIdList := []int{185} // 章节报告,但是需要统计成普通报告
  21. adminIdList := make([]int, 0)
  22. adminIdMap := make(map[int]string)
  23. adminClassifyMap := make(map[int]map[int]*models.ExportReportItem)
  24. type ClassifyItem struct {
  25. ClassifyIdFirst int
  26. ClassifyNameFirst string
  27. ClassifyIdSecond int
  28. ClassifyNameSecond string
  29. }
  30. classifyIdMap := make(map[int]ClassifyItem)
  31. realClassifyIdFirstMap := make(map[int]bool)
  32. realFirstClassifyIdSecondMap := make(map[int]map[int]bool)
  33. // 普通报告
  34. exportReportList, err := models.GetExportReportList(startDate, endDate, otherReportClassifyIdList)
  35. if err != nil {
  36. fmt.Println(fmt.Sprintf("获取普通报告列表失败:%s", err.Error()))
  37. return
  38. }
  39. for _, v := range exportReportList {
  40. _, ok := adminIdMap[v.AdminId]
  41. if !ok {
  42. adminIdList = append(adminIdList, v.AdminId)
  43. adminIdMap[v.AdminId] = v.AdminName
  44. adminClassifyMap[v.AdminId] = make(map[int]*models.ExportReportItem)
  45. }
  46. _, ok = classifyIdMap[v.ClassifyIdFirst]
  47. if !ok {
  48. classifyItem := ClassifyItem{
  49. ClassifyIdFirst: v.ClassifyIdFirst,
  50. ClassifyNameFirst: v.ClassifyNameFirst,
  51. }
  52. classifyIdMap[v.ClassifyIdFirst] = classifyItem
  53. realClassifyIdFirstMap[v.ClassifyIdFirst] = true
  54. }
  55. adminClassifyMap[v.AdminId][v.ClassifyIdFirst] = v
  56. }
  57. // 章节报告
  58. exportReportChapterList, err := models.GetExportReportChapterList(startDate, endDate, otherReportClassifyIdList)
  59. if err != nil {
  60. fmt.Println(fmt.Sprintf("获取章节报告列表失败:%s", err.Error()))
  61. return
  62. }
  63. for _, v := range exportReportChapterList {
  64. _, ok := adminIdMap[v.AdminId]
  65. if !ok {
  66. adminIdList = append(adminIdList, v.AdminId)
  67. adminIdMap[v.AdminId] = v.AdminName
  68. adminClassifyMap[v.AdminId] = make(map[int]*models.ExportReportItem)
  69. }
  70. _, ok = classifyIdMap[v.ClassifyIdFirst]
  71. if !ok {
  72. classifyIdMap[v.ClassifyIdFirst] = ClassifyItem{
  73. ClassifyIdFirst: v.ClassifyIdFirst,
  74. ClassifyNameFirst: v.ClassifyNameFirst,
  75. }
  76. realClassifyIdFirstMap[v.ClassifyIdFirst] = true
  77. }
  78. if exportReportItem, ok := adminClassifyMap[v.AdminId][v.ClassifyIdFirst]; ok {
  79. v.Total = exportReportItem.Total + v.Total
  80. }
  81. adminClassifyMap[v.AdminId][v.ClassifyIdFirst] = v
  82. }
  83. // 特殊的报告列表(本身是章节报告,可是却要统计在普通报告里面)
  84. exportOtherReportList, err := models.GetExportReportListByClassifyIdList(startDate, endDate, onlyReportClassifyIdList)
  85. if err != nil {
  86. fmt.Println(fmt.Sprintf("获取特殊的报告列表失败:%s", err.Error()))
  87. return
  88. }
  89. // 其他类型的报告
  90. for _, v := range exportOtherReportList {
  91. _, ok := adminIdMap[v.AdminId]
  92. if !ok {
  93. adminIdList = append(adminIdList, v.AdminId)
  94. adminIdMap[v.AdminId] = v.AdminName
  95. adminClassifyMap[v.AdminId] = make(map[int]*models.ExportReportItem)
  96. }
  97. _, ok = classifyIdMap[v.ClassifyIdFirst]
  98. if !ok {
  99. classifyIdMap[v.ClassifyIdFirst] = ClassifyItem{
  100. ClassifyIdFirst: v.ClassifyIdFirst,
  101. ClassifyNameFirst: v.ClassifyNameFirst,
  102. }
  103. realClassifyIdFirstMap[v.ClassifyIdFirst] = true
  104. }
  105. if exportReportItem, ok := adminClassifyMap[v.AdminId][v.ClassifyIdFirst]; ok {
  106. v.Total = exportReportItem.Total + v.Total
  107. }
  108. adminClassifyMap[v.AdminId][v.ClassifyIdFirst] = v
  109. }
  110. // 特殊的报告列表(本身是章节报告,可是却要统计在普通报告里面)
  111. exportHongGuanReportList, err := models.GetExportHongGuanReportListByClassifyIdList(startDate, endDate, hongGuanReportClassifyId)
  112. if err != nil {
  113. fmt.Println(fmt.Sprintf("获取宏观报告列表失败:%s", err.Error()))
  114. return
  115. }
  116. // 宏观报告类型的报告
  117. for _, v := range exportHongGuanReportList {
  118. _, ok := adminIdMap[v.AdminId]
  119. if !ok {
  120. adminIdList = append(adminIdList, v.AdminId)
  121. adminIdMap[v.AdminId] = v.AdminName
  122. adminClassifyMap[v.AdminId] = make(map[int]*models.ExportReportItem)
  123. }
  124. _, ok = classifyIdMap[v.ClassifyIdSecond]
  125. if !ok {
  126. classifyIdMap[v.ClassifyIdSecond] = ClassifyItem{
  127. ClassifyIdFirst: v.ClassifyIdFirst,
  128. ClassifyNameFirst: v.ClassifyNameFirst,
  129. ClassifyIdSecond: v.ClassifyIdSecond,
  130. ClassifyNameSecond: v.ClassifyNameSecond,
  131. }
  132. //realClassifyIdFirstMap[v.ClassifyIdFirst] = true
  133. }
  134. _, ok = realFirstClassifyIdSecondMap[v.ClassifyIdFirst]
  135. if !ok {
  136. realFirstClassifyIdSecondMap[v.ClassifyIdFirst] = make(map[int]bool)
  137. }
  138. realFirstClassifyIdSecondMap[v.ClassifyIdFirst][v.ClassifyIdSecond] = true
  139. if exportReportItem, ok := adminClassifyMap[v.AdminId][v.ClassifyIdSecond]; ok {
  140. v.Total = exportReportItem.Total + v.Total
  141. }
  142. adminClassifyMap[v.AdminId][v.ClassifyIdSecond] = v
  143. }
  144. // 语音播报的数据
  145. voiceBroadcastStat, err := models.GetExportVoiceBroadcastList(startDate, endDate)
  146. if err != nil {
  147. fmt.Println(fmt.Sprintf("获取语音播报列表失败:%s", err.Error()))
  148. return
  149. }
  150. adminNameMap := map[string]int{
  151. `姚昕泽`: 251,
  152. `张立舟`: 466,
  153. `郑露`: 478,
  154. `方正`: 761,
  155. }
  156. voiceBroadcastMap := make(map[int]int)
  157. for _, voiceBroadcast := range voiceBroadcastStat {
  158. adminId, ok := adminNameMap[voiceBroadcast.AdminName]
  159. if !ok {
  160. panic(voiceBroadcast.AdminName + "未匹配到系统用户ID")
  161. }
  162. voiceBroadcastMap[adminId] = voiceBroadcast.Total
  163. }
  164. //dir, _ := os.Executable()
  165. //exPath := filepath.Dir(dir)
  166. //
  167. //downLoadnFilePath := exPath + "/研究员报告统计.xlsx"
  168. downLoadnFilePath := "static/imgs/研究员报告统计.xlsx"
  169. xlsxFile := xlsx.NewFile()
  170. if err != nil {
  171. fmt.Println("新增Sheet失败", err.Error())
  172. return
  173. }
  174. //sheetNew.SetColWidth()
  175. // 获取研究员报告统计
  176. sheetNew, _ := xlsxFile.AddSheet("研究员报告统计")
  177. titleRow := sheetNew.AddRow()
  178. titleRow.AddCell().SetValue("研究员")
  179. classifyFirstIdList := []int{124, 180, 179, 181, 42, 125, 214, 96, 91, 129, 175, 185}
  180. classifySecondIdMap := make(map[int][]int)
  181. classifySecondIdMap[91] = []int{55, 93, 94, 113, 114, 154, 161, 197, 208, 224, 226, 227, 228, 239}
  182. sortClassifyIdList := make([]int, 0)
  183. for k, classifyFirstId := range classifyFirstIdList {
  184. if k == 1 {
  185. // 语音播报需要插在第二列
  186. titleRow.AddCell().SetValue(`语音播报`)
  187. }
  188. if tmpClassifySecondIdList, ok := classifySecondIdMap[classifyFirstId]; ok {
  189. // 该一级分类下真实的二级分类列表
  190. realClassifyIdSecondMap := realFirstClassifyIdSecondMap[classifyFirstId]
  191. for _, classifySecondId := range tmpClassifySecondIdList {
  192. classifyName := ``
  193. if classifyItem, ok := classifyIdMap[classifySecondId]; ok {
  194. classifyName = fmt.Sprintf("%s \n(%s)", classifyItem.ClassifyNameFirst, classifyItem.ClassifyNameSecond)
  195. }
  196. titleRow.AddCell().SetValue(classifyName)
  197. delete(realClassifyIdSecondMap, classifySecondId)
  198. sortClassifyIdList = append(sortClassifyIdList, classifySecondId)
  199. }
  200. // 后面新加的二级分类
  201. for classifySecondId, _ := range realClassifyIdSecondMap {
  202. classifyName := ``
  203. if classifyItem, ok := classifyIdMap[classifySecondId]; ok {
  204. classifyName = fmt.Sprintf("%s \n(%s)", classifyItem.ClassifyNameFirst, classifyItem.ClassifyNameSecond)
  205. }
  206. titleRow.AddCell().SetValue(classifyName)
  207. delete(realClassifyIdSecondMap, classifySecondId)
  208. sortClassifyIdList = append(sortClassifyIdList, classifySecondId)
  209. }
  210. } else {
  211. classifyName := ``
  212. if classifyItem, ok := classifyIdMap[classifyFirstId]; ok {
  213. classifyName = classifyItem.ClassifyNameFirst
  214. }
  215. titleRow.AddCell().SetValue(classifyName)
  216. delete(realClassifyIdFirstMap, classifyFirstId)
  217. sortClassifyIdList = append(sortClassifyIdList, classifyFirstId)
  218. }
  219. }
  220. // 后面新加的一级分类
  221. for classifyFirstId, _ := range realClassifyIdFirstMap {
  222. classifyName := ``
  223. if classifyItem, ok := classifyIdMap[classifyFirstId]; ok {
  224. classifyName = classifyItem.ClassifyNameFirst
  225. }
  226. titleRow.AddCell().SetValue(classifyName)
  227. delete(realClassifyIdFirstMap, classifyFirstId)
  228. sortClassifyIdList = append(sortClassifyIdList, classifyFirstId)
  229. }
  230. for adminId, classifyMap := range adminClassifyMap {
  231. dataRow := sheetNew.AddRow()
  232. dataRow.AddCell().SetValue(adminIdMap[adminId])
  233. for k, classifyId := range sortClassifyIdList {
  234. if k == 1 { // 语音播报
  235. dataRow.AddCell().SetValue(voiceBroadcastMap[adminId])
  236. }
  237. reportItem, ok := classifyMap[classifyId]
  238. total := 0
  239. if ok {
  240. total = reportItem.Total
  241. }
  242. dataRow.AddCell().SetValue(total)
  243. }
  244. }
  245. // 路演统计
  246. err = exportRoadShowReport(startDate, endDate, xlsxFile)
  247. if err != nil {
  248. fmt.Println("路演统计失败,err:", err)
  249. return
  250. }
  251. // 英文研报统计
  252. err = exportEnglishReport(startDate, endDate, xlsxFile)
  253. if err != nil {
  254. fmt.Println("英文研报统计失败,err:", err)
  255. return
  256. }
  257. err = xlsxFile.Save(downLoadnFilePath)
  258. if err != nil {
  259. fmt.Println("保存文件失败,err:", err)
  260. return
  261. }
  262. fmt.Println("操作完成")
  263. }
  264. // exportRoadShowReport
  265. // @Description: 路演统计
  266. // @param startDate
  267. // @param endDate
  268. // @param xlsxFile
  269. // @return err
  270. func exportRoadShowReport(startDate, endDate string, xlsxFile *xlsx.File) (err error) {
  271. sheetNew, _ := xlsxFile.AddSheet("研究员路演统计")
  272. titleRow := sheetNew.AddRow()
  273. titleRow.AddCell().SetValue("研究员")
  274. titleRow.AddCell().SetValue("试用路演(已反馈)")
  275. titleRow.AddCell().SetValue("试用路演(未反馈)")
  276. titleRow.AddCell().SetValue("正式路演(已反馈)")
  277. titleRow.AddCell().SetValue("正式路演(未反馈)")
  278. titleRow.AddCell().SetValue("公开会议")
  279. userList, err := roadshow.GetResearcherListV2()
  280. if err != nil {
  281. fmt.Println(`获取用户失败`)
  282. return
  283. }
  284. userMap := make(map[int]bool)
  285. for _, v := range userList {
  286. userMap[v.AdminId] = true
  287. }
  288. adminDataMap, err := getResearcherSectionData(startDate, endDate)
  289. if err != nil {
  290. fmt.Println("获取时间区间数据失败:", err.Error())
  291. return
  292. }
  293. for adminId, adminName := range adminDataMap.AdminIdMap {
  294. if !userMap[adminId] {
  295. continue
  296. }
  297. dataRow := sheetNew.AddRow()
  298. dataRow.AddCell().SetValue(adminName)
  299. // 试用路演
  300. askTryOutNum := adminDataMap.AskTryOutMap[adminId]
  301. noAskTryOutNum := adminDataMap.TryOutMap[adminId] - askTryOutNum
  302. dataRow.AddCell().SetValue(askTryOutNum)
  303. dataRow.AddCell().SetValue(noAskTryOutNum)
  304. // 正式路演
  305. askFormalNum := adminDataMap.AskFormalMap[adminId]
  306. noAskFormalNum := adminDataMap.FormalMap[adminId] - askFormalNum
  307. dataRow.AddCell().SetValue(askFormalNum)
  308. dataRow.AddCell().SetValue(noAskFormalNum)
  309. // 公开会议
  310. dataRow.AddCell().SetValue(adminDataMap.MeetingMap[adminId])
  311. }
  312. return
  313. }
  314. type AdminDataMap struct {
  315. TryOutMap map[int]int `description:"试用路演次数"`
  316. FormalMap map[int]int `description:"正式路演次数"`
  317. MeetingMap map[int]int `description:"会议次数"`
  318. AskTryOutMap map[int]int `description:"试用路演次数(已反馈)"`
  319. AskFormalMap map[int]int `description:"正式路演次数(已反馈)"`
  320. StartDate string `description:"开始日期"`
  321. EndDate string `description:"开始日期"`
  322. AdminIdMap map[int]string `description:"系统用户名称"`
  323. }
  324. // getResearcherSectionData 获取研究员周期数据
  325. func getResearcherSectionData(startDateStr, endDateStr string) (adminDataMap AdminDataMap, err error) {
  326. startDate, _ := time.ParseInLocation(utils.FormatDateTime, startDateStr, time.Local)
  327. endDate, _ := time.ParseInLocation(utils.FormatDateTime, endDateStr, time.Local)
  328. endDate = endDate.Add(-1 * time.Second) //本月最后一天
  329. tryOutMap := make(map[int]int)
  330. formalMap := make(map[int]int)
  331. meetingMap := make(map[int]int)
  332. asktryOutMap := make(map[int]int) //填写过客户问答的路演次数(试用)
  333. askformalMap := make(map[int]int) //填写过客户问答的路演次数(正式)
  334. adminIdMap := make(map[int]string) //系统用户名称
  335. //正式客户
  336. {
  337. var condition string
  338. var pars []interface{}
  339. condition = ` and start_date >= ? and end_date <= ? and company_status = ? `
  340. pars = append(pars, startDate, endDate, "正式")
  341. data, tmpErr := roadshow.GetGroupResearcherRecordList(condition, pars)
  342. if tmpErr != nil {
  343. err = tmpErr
  344. return
  345. }
  346. for _, v := range data {
  347. formalMap[v.AdminId] = v.Num
  348. adminIdMap[v.AdminId] = v.AdminName
  349. }
  350. var conditionAsk string
  351. var parsAsk []interface{}
  352. conditionAsk = ` and c.question_status = 1 and a.start_date >= ? and a.end_date <= ? and a.company_status = ? `
  353. parsAsk = append(parsAsk, startDate, endDate, "正式")
  354. dataAsk, tmpErr := roadshow.GetGroupResearcherRecordListAsk(conditionAsk, parsAsk)
  355. if tmpErr != nil {
  356. err = tmpErr
  357. return
  358. }
  359. for _, v := range dataAsk {
  360. askformalMap[v.AdminId] = v.Num
  361. adminIdMap[v.AdminId] = v.AdminName
  362. }
  363. }
  364. //试用客户
  365. {
  366. var condition string
  367. var pars []interface{}
  368. condition = ` and start_date >= ? and end_date <= ? and company_status = ? `
  369. pars = append(pars, startDate, endDate, "试用")
  370. data, tmpErr := roadshow.GetGroupResearcherRecordList(condition, pars)
  371. if tmpErr != nil {
  372. err = tmpErr
  373. return
  374. }
  375. for _, v := range data {
  376. //fmt.Println(v)
  377. tryOutMap[v.AdminId] = v.Num
  378. adminIdMap[v.AdminId] = v.AdminName
  379. }
  380. var conditionAsk string
  381. var parsAsk []interface{}
  382. conditionAsk = ` and c.question_status = 1 and a.start_date >= ? and a.end_date <= ? and a.company_status = ? `
  383. parsAsk = append(parsAsk, startDate, endDate, "试用")
  384. dataAsk, tmpErr := roadshow.GetGroupResearcherRecordListAsk(conditionAsk, parsAsk)
  385. if tmpErr != nil {
  386. err = tmpErr
  387. return
  388. }
  389. for _, v := range dataAsk {
  390. asktryOutMap[v.AdminId] = v.Num
  391. adminIdMap[v.AdminId] = v.AdminName
  392. }
  393. }
  394. //公开会议
  395. {
  396. var condition string
  397. var pars []interface{}
  398. condition = ` and start_date >= ? and end_date <= ? and activity_type = ? `
  399. pars = append(pars, startDate, endDate, "公开会议")
  400. data, tmpErr := roadshow.GetGroupResearcherRecordList(condition, pars)
  401. if tmpErr != nil {
  402. err = tmpErr
  403. return
  404. }
  405. for _, v := range data {
  406. //fmt.Println(v)
  407. meetingMap[v.AdminId] = v.Num
  408. adminIdMap[v.AdminId] = v.AdminName
  409. }
  410. }
  411. adminDataMap = AdminDataMap{
  412. TryOutMap: tryOutMap,
  413. FormalMap: formalMap,
  414. MeetingMap: meetingMap,
  415. AdminIdMap: adminIdMap,
  416. AskTryOutMap: asktryOutMap,
  417. AskFormalMap: askformalMap,
  418. StartDate: startDate.Format(utils.FormatDate),
  419. EndDate: endDate.Format(utils.FormatDate),
  420. }
  421. return
  422. }
  423. // exportRoadShowReport
  424. // @Description: 路演统计
  425. // @param startDate
  426. // @param endDate
  427. // @param xlsxFile
  428. // @return err
  429. func exportEnglishReport(startDate, endDate string, xlsxFile *xlsx.File) (err error) {
  430. sheetNew, _ := xlsxFile.AddSheet("研究员英文报告统计")
  431. titleRow := sheetNew.AddRow()
  432. titleRow.AddCell().SetValue("研究员")
  433. adminIdList := make([]int, 0)
  434. adminIdMap := make(map[int]string)
  435. adminClassifyMap := make(map[int]map[int]*models.ExportEnglishReportItem)
  436. type ClassifyItem struct {
  437. ClassifyIdFirst int
  438. ClassifyNameFirst string
  439. ClassifyIdSecond int
  440. ClassifyNameSecond string
  441. ClassifyIdThird int
  442. ClassifyNameThird string
  443. }
  444. classifyIdMap := make(map[int]ClassifyItem)
  445. realClassifyIdFirstMap := make(map[int]bool)
  446. realClassifyIdSecondMap := make(map[int]bool)
  447. realClassifyIdThirdMap := make(map[int]bool)
  448. // 父级与子级的关系
  449. classifyIdChildIdMap := make(map[int]map[int]bool)
  450. // 普通报告
  451. exportReportList, err := models.GetExportEnglishReportList(startDate, endDate)
  452. if err != nil {
  453. fmt.Println(fmt.Sprintf("获取普通报告列表失败:%s", err.Error()))
  454. return
  455. }
  456. //
  457. classifySecondIdList := make([]int, 0)
  458. for _, v := range exportReportList {
  459. classifySecondIdList = append(classifySecondIdList, v.SecondClassifyId)
  460. }
  461. obj := models.EnglishClassify{}
  462. secondClassifyList, err := obj.GetClassifyListByIdList(classifySecondIdList)
  463. if err != nil {
  464. fmt.Println(fmt.Sprintf("获取一级分类列表失败:%s", err.Error()))
  465. return
  466. }
  467. // 二级分类与一级分类的关系
  468. secondAndFirstMap := make(map[int]int)
  469. firstIdList := make([]int, 0)
  470. for _, v := range secondClassifyList {
  471. secondAndFirstMap[v.Id] = v.ParentId
  472. firstIdList = append(firstIdList, v.ParentId)
  473. }
  474. // 一级分类信息
  475. firstIdNameMap := make(map[int]string)
  476. {
  477. firstClassifyList, tmpErr := obj.GetClassifyListByIdList(firstIdList)
  478. if tmpErr != nil {
  479. fmt.Println(fmt.Sprintf("获取一级分类列表失败:%s", tmpErr.Error()))
  480. err = tmpErr
  481. return
  482. }
  483. for _, v := range firstClassifyList {
  484. firstIdNameMap[v.Id] = v.ClassifyName
  485. realClassifyIdFirstMap[v.Id] = true
  486. }
  487. }
  488. for _, v := range exportReportList {
  489. _, ok := adminIdMap[v.AdminId]
  490. if !ok {
  491. adminIdList = append(adminIdList, v.AdminId)
  492. adminIdMap[v.AdminId] = v.AdminName
  493. adminClassifyMap[v.AdminId] = make(map[int]*models.ExportEnglishReportItem)
  494. }
  495. _, ok = classifyIdMap[v.ThirdClassifyId]
  496. if !ok {
  497. classifyItem := ClassifyItem{
  498. ClassifyIdSecond: v.SecondClassifyId,
  499. ClassifyNameSecond: v.SecondClassifyName,
  500. ClassifyIdThird: v.ThirdClassifyId,
  501. ClassifyNameThird: v.ThirdClassifyName,
  502. }
  503. firstId, ok := secondAndFirstMap[v.SecondClassifyId]
  504. if !ok {
  505. err = errors.New(`找不到父级分类id`)
  506. return
  507. }
  508. firstClassifyName, ok := firstIdNameMap[firstId]
  509. if !ok {
  510. err = errors.New(`找不到父级分类名称`)
  511. return
  512. }
  513. classifyItem.ClassifyIdFirst = firstId
  514. classifyItem.ClassifyNameFirst = firstClassifyName
  515. classifyIdMap[v.ThirdClassifyId] = classifyItem
  516. if classifyItem.ClassifyIdSecond > 0 {
  517. realClassifyIdSecondMap[classifyItem.ClassifyIdSecond] = true
  518. // 一级与二级的关系
  519. _, ok = classifyIdChildIdMap[classifyItem.ClassifyIdFirst]
  520. if !ok {
  521. classifyIdChildIdMap[classifyItem.ClassifyIdFirst] = make(map[int]bool)
  522. }
  523. classifyIdChildIdMap[classifyItem.ClassifyIdFirst][classifyItem.ClassifyIdSecond] = true
  524. }
  525. if classifyItem.ClassifyIdThird > 0 {
  526. realClassifyIdThirdMap[classifyItem.ClassifyIdThird] = true
  527. // 二级与三级的关系
  528. _, ok = classifyIdChildIdMap[classifyItem.ClassifyIdSecond]
  529. if !ok {
  530. classifyIdChildIdMap[classifyItem.ClassifyIdSecond] = make(map[int]bool)
  531. }
  532. classifyIdChildIdMap[classifyItem.ClassifyIdSecond][classifyItem.ClassifyIdThird] = true
  533. }
  534. }
  535. adminClassifyMap[v.AdminId][v.ThirdClassifyId] = v
  536. }
  537. realClassifyIdFirstList := getSortInt(realClassifyIdFirstMap)
  538. realClassifyIdSecondList := getSortInt(realClassifyIdSecondMap)
  539. realClassifyIdThirdList := getSortInt(realClassifyIdThirdMap)
  540. sortClassifyIdList := make([]int, 0)
  541. for _, firstId := range realClassifyIdFirstList {
  542. secondIdMap, ok := classifyIdChildIdMap[firstId]
  543. if !ok {
  544. fmt.Println("遍历realClassifyIdFirstList找不到一级分类Id")
  545. }
  546. for _, secondId := range realClassifyIdSecondList {
  547. if _, ok = secondIdMap[secondId]; !ok {
  548. continue
  549. }
  550. thirdIdMap, ok := classifyIdChildIdMap[secondId]
  551. if !ok {
  552. fmt.Println("遍历realClassifyIdFirstList找不到二级分类Id")
  553. }
  554. for _, thirdId := range realClassifyIdThirdList {
  555. if _, ok = thirdIdMap[thirdId]; !ok {
  556. continue
  557. }
  558. classifyName := ``
  559. classifyItem, ok := classifyIdMap[thirdId]
  560. if ok {
  561. classifyName = fmt.Sprintf("%s\n(%s)\n(%s)", classifyItem.ClassifyNameFirst, classifyItem.ClassifyNameSecond, classifyItem.ClassifyNameThird)
  562. }
  563. titleRow.AddCell().SetValue(classifyName)
  564. sortClassifyIdList = append(sortClassifyIdList, thirdId)
  565. }
  566. }
  567. }
  568. for adminId, classifyMap := range adminClassifyMap {
  569. dataRow := sheetNew.AddRow()
  570. dataRow.AddCell().SetValue(adminIdMap[adminId])
  571. for _, classifyId := range sortClassifyIdList {
  572. reportItem, ok := classifyMap[classifyId]
  573. total := 0
  574. if ok {
  575. total = reportItem.Total
  576. }
  577. dataRow.AddCell().SetValue(total)
  578. }
  579. }
  580. return
  581. }
  582. func getSortInt(classifyIdMap map[int]bool) []int {
  583. // 1. 提取所有的 key 到切片中
  584. keys := make([]int, 0, len(classifyIdMap))
  585. for k := range classifyIdMap {
  586. keys = append(keys, k)
  587. }
  588. // 2. 对 key 进行升序排序
  589. sort.Ints(keys)
  590. return keys
  591. }