You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

user_data_analysis.go 11 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. package repo
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "strings"
  7. "time"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/context"
  10. "code.gitea.io/gitea/modules/git"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/services/mailer"
  14. "github.com/360EntSecGroup-Skylar/excelize/v2"
  15. )
  16. func DownloadAllUserData(ctx *context.Context) {
  17. re, count := models.QueryUserStaticDataAll(pageOpts)
  18. log.Info("return count=" + fmt.Sprint(count))
  19. //writer exec file.
  20. xlsx := excelize.NewFile()
  21. sheetName := ctx.Tr("user.static.sheetname")
  22. index := xlsx.NewSheet(sheetName)
  23. xlsx.DeleteSheet("Sheet1")
  24. dataHeader := map[string]string{
  25. "A1": ctx.Tr("user.static.id"),
  26. "B1": ctx.Tr("user.static.name"),
  27. "C1": ctx.Tr("user.static.codemergecount"),
  28. "D1": ctx.Tr("user.static.commitcount"),
  29. "E1": ctx.Tr("user.static.issuecount"),
  30. "F1": ctx.Tr("user.static.commentcount"),
  31. "G1": ctx.Tr("user.static.focusrepocount"),
  32. "H1": ctx.Tr("user.static.starrepocount"),
  33. "I1": ctx.Tr("user.static.logincount"),
  34. "J1": ctx.Tr("user.static.watchedcount"),
  35. "K1": ctx.Tr("user.static.commitcodesize"),
  36. "L1": ctx.Tr("user.static.solveissuecount"),
  37. "M1": ctx.Tr("user.static.encyclopediascount"),
  38. "N1": ctx.Tr("user.static.createrepocount"),
  39. "O1": ctx.Tr("user.static.openiindex"),
  40. "P1": ctx.Tr("user.static.registdate"),
  41. "Q1": ctx.Tr("user.static.countdate"),
  42. }
  43. for k, v := range dataHeader {
  44. //设置单元格的值
  45. xlsx.SetCellValue(sheetName, k, v)
  46. }
  47. for i, userRecord := range re {
  48. rows := fmt.Sprint(i + 2)
  49. xlsx.SetCellValue(sheetName, "A"+rows, userRecord.ID)
  50. xlsx.SetCellValue(sheetName, "B"+rows, userRecord.Name)
  51. xlsx.SetCellValue(sheetName, "C"+rows, userRecord.CodeMergeCount)
  52. xlsx.SetCellValue(sheetName, "D"+rows, userRecord.CommitCount)
  53. xlsx.SetCellValue(sheetName, "E"+rows, userRecord.IssueCount)
  54. xlsx.SetCellValue(sheetName, "F"+rows, userRecord.CommentCount)
  55. xlsx.SetCellValue(sheetName, "G"+rows, userRecord.FocusRepoCount)
  56. xlsx.SetCellValue(sheetName, "H"+rows, userRecord.StarRepoCount)
  57. xlsx.SetCellValue(sheetName, "I"+rows, userRecord.LoginCount)
  58. xlsx.SetCellValue(sheetName, "J"+rows, userRecord.WatchedCount)
  59. xlsx.SetCellValue(sheetName, "K"+rows, userRecord.CommitCodeSize)
  60. xlsx.SetCellValue(sheetName, "L"+rows, userRecord.SolveIssueCount)
  61. xlsx.SetCellValue(sheetName, "M"+rows, userRecord.EncyclopediasCount)
  62. xlsx.SetCellValue(sheetName, "N"+rows, userRecord.CreateRepoCount)
  63. xlsx.SetCellValue(sheetName, "O"+rows, fmt.Sprintf("%.2f", userRecord.OpenIIndex))
  64. formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05")
  65. xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3])
  66. formatTime = time.Unix(userRecord.CountDate, 0).Format("2006-01-02 15:04:05")
  67. xlsx.SetCellValue(sheetName, "Q"+rows, formatTime[0:len(formatTime)-3])
  68. }
  69. //设置默认打开的表单
  70. xlsx.SetActiveSheet(index)
  71. var filename string
  72. filename = sheetName + "_" + ctx.Tr("user.static.all") + ".xlsx"
  73. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(filename))
  74. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  75. if _, err := xlsx.WriteTo(ctx.Resp); err != nil {
  76. log.Info("writer exel error." + err.Error())
  77. }
  78. }
  79. func QueryUserStaticDataPage(ctx *context.Context) {
  80. startDate := ctx.Query("startDate")
  81. endDate := ctx.Query("endDate")
  82. page := ctx.QueryInt("page")
  83. if page <= 0 {
  84. page = 1
  85. }
  86. pageSize := ctx.QueryInt("pageSize")
  87. if pageSize <= 0 {
  88. pageSize = setting.UI.IssuePagingNum
  89. }
  90. userName := ctx.Query("userName")
  91. IsReturnFile := ctx.QueryBool("IsReturnFile")
  92. log.Info("startDate=" + startDate + " endDate=" + endDate + " userName=" + userName + " page=" + fmt.Sprint(page))
  93. var startTime time.Time
  94. var endTime time.Time
  95. var isAll bool
  96. if startDate == "all" {
  97. isAll = true
  98. startTime = time.Now()
  99. endTime = time.Now()
  100. } else {
  101. startTime, _ = time.ParseInLocation("2006-01-02", startDate, time.Local)
  102. settingStartTime, _ := time.Parse("2006-01-02", setting.RadarMap.RecordBeginTime)
  103. if startTime.Unix() < settingStartTime.Unix() {
  104. startTime = settingStartTime
  105. startDate = settingStartTime.Format("2006-01-02")
  106. }
  107. endTime, _ = time.ParseInLocation("2006-01-02", endDate, time.Local)
  108. endTime = endTime.AddDate(0, 0, 1)
  109. isAll = false
  110. log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix()))
  111. }
  112. if IsReturnFile {
  113. page = -1
  114. pageSize = -1
  115. }
  116. pageOpts := &models.UserBusinessAnalysisQueryOptions{
  117. ListOptions: models.ListOptions{
  118. Page: page,
  119. PageSize: pageSize,
  120. },
  121. UserName: userName,
  122. StartTime: startTime.Unix(),
  123. EndTime: endTime.Unix(),
  124. IsAll: isAll,
  125. }
  126. if IsReturnFile {
  127. re, count := models.QueryUserStaticDataAll(pageOpts)
  128. log.Info("return count=" + fmt.Sprint(count))
  129. //writer exec file.
  130. xlsx := excelize.NewFile()
  131. sheetName := ctx.Tr("user.static.sheetname")
  132. index := xlsx.NewSheet(sheetName)
  133. xlsx.DeleteSheet("Sheet1")
  134. dataHeader := map[string]string{
  135. "A1": ctx.Tr("user.static.id"),
  136. "B1": ctx.Tr("user.static.name"),
  137. "C1": ctx.Tr("user.static.codemergecount"),
  138. "D1": ctx.Tr("user.static.commitcount"),
  139. "E1": ctx.Tr("user.static.issuecount"),
  140. "F1": ctx.Tr("user.static.commentcount"),
  141. "G1": ctx.Tr("user.static.focusrepocount"),
  142. "H1": ctx.Tr("user.static.starrepocount"),
  143. "I1": ctx.Tr("user.static.logincount"),
  144. "J1": ctx.Tr("user.static.watchedcount"),
  145. "K1": ctx.Tr("user.static.commitcodesize"),
  146. "L1": ctx.Tr("user.static.solveissuecount"),
  147. "M1": ctx.Tr("user.static.encyclopediascount"),
  148. "N1": ctx.Tr("user.static.createrepocount"),
  149. "O1": ctx.Tr("user.static.openiindex"),
  150. "P1": ctx.Tr("user.static.registdate"),
  151. "Q1": ctx.Tr("user.static.countdate"),
  152. }
  153. for k, v := range dataHeader {
  154. //设置单元格的值
  155. xlsx.SetCellValue(sheetName, k, v)
  156. }
  157. for i, userRecord := range re {
  158. rows := fmt.Sprint(i + 2)
  159. xlsx.SetCellValue(sheetName, "A"+rows, userRecord.ID)
  160. xlsx.SetCellValue(sheetName, "B"+rows, userRecord.Name)
  161. xlsx.SetCellValue(sheetName, "C"+rows, userRecord.CodeMergeCount)
  162. xlsx.SetCellValue(sheetName, "D"+rows, userRecord.CommitCount)
  163. xlsx.SetCellValue(sheetName, "E"+rows, userRecord.IssueCount)
  164. xlsx.SetCellValue(sheetName, "F"+rows, userRecord.CommentCount)
  165. xlsx.SetCellValue(sheetName, "G"+rows, userRecord.FocusRepoCount)
  166. xlsx.SetCellValue(sheetName, "H"+rows, userRecord.StarRepoCount)
  167. xlsx.SetCellValue(sheetName, "I"+rows, userRecord.LoginCount)
  168. xlsx.SetCellValue(sheetName, "J"+rows, userRecord.WatchedCount)
  169. xlsx.SetCellValue(sheetName, "K"+rows, userRecord.CommitCodeSize)
  170. xlsx.SetCellValue(sheetName, "L"+rows, userRecord.SolveIssueCount)
  171. xlsx.SetCellValue(sheetName, "M"+rows, userRecord.EncyclopediasCount)
  172. xlsx.SetCellValue(sheetName, "N"+rows, userRecord.CreateRepoCount)
  173. xlsx.SetCellValue(sheetName, "O"+rows, fmt.Sprintf("%.2f", userRecord.OpenIIndex))
  174. formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05")
  175. xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3])
  176. formatTime = userRecord.DataDate
  177. xlsx.SetCellValue(sheetName, "Q"+rows, formatTime+" 00:01")
  178. }
  179. //设置默认打开的表单
  180. xlsx.SetActiveSheet(index)
  181. var filename string
  182. nowTime := time.Now()
  183. nowZeroTime := time.Date(nowTime.Year(), nowTime.Month(), nowTime.Day(), 0, 0, 0, 0, nowTime.Location())
  184. if endTime.Unix() >= nowZeroTime.Unix() {
  185. endDate = nowZeroTime.AddDate(0, 0, -1).Format("2006-01-02")
  186. }
  187. if isAll {
  188. filename = sheetName + "_" + ctx.Tr("user.static.all") + ".xlsx"
  189. } else {
  190. filename = sheetName + "_" + strings.ReplaceAll(startDate, "-", "") + "_" + strings.ReplaceAll(endDate, "-", "") + ".xlsx"
  191. }
  192. if len(userName) > 0 {
  193. filename = sheetName + "_" + userName + "_" + strings.ReplaceAll(startDate, "-", "") + "_" + strings.ReplaceAll(endDate, "-", "") + ".xlsx"
  194. }
  195. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(filename))
  196. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  197. if _, err := xlsx.WriteTo(ctx.Resp); err != nil {
  198. log.Info("writer exel error." + err.Error())
  199. }
  200. } else {
  201. mapInterface := make(map[string]interface{})
  202. re, count := models.QueryUserStaticDataPage(pageOpts)
  203. mapInterface["data"] = re
  204. mapInterface["count"] = count
  205. ctx.JSON(http.StatusOK, mapInterface)
  206. }
  207. }
  208. func TimingCountDataByDateAndReCount(date string, isReCount bool) {
  209. if date == "refreshAll" {
  210. models.RefreshUserStaticAllTabel()
  211. return
  212. }
  213. t, _ := time.Parse("2006-01-02", date)
  214. startTime := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
  215. endTime := time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, t.Location())
  216. //query wiki data
  217. log.Info("start to time count data")
  218. wikiMap := make(map[string]int)
  219. warnEmailMessage := "用户统计信息入库失败,请尽快定位。"
  220. repoList, err := models.GetAllRepositories()
  221. if err != nil {
  222. log.Error("query repo error." + err.Error())
  223. mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
  224. return
  225. }
  226. log.Info("start to query wiki data")
  227. for _, repoRecord := range repoList {
  228. wikiPath := models.WikiPath(repoRecord.OwnerName, repoRecord.Name)
  229. time, err := git.GetLatestCommitTime(wikiPath)
  230. if err == nil {
  231. log.Info("last commit time:" + time.Format("2006-01-02 15:04:05") + " wikiPath=" + wikiPath)
  232. if time.After(startTime) {
  233. wikiRepo, _, err := FindWikiRepoCommitByWikiPath(wikiPath)
  234. if err != nil {
  235. log.Error("wiki not exist. wikiPath=" + wikiPath)
  236. } else {
  237. log.Info("wiki exist, wikiPath=" + wikiPath)
  238. list, err := wikiRepo.GetCommitByPathAndDays(wikiPath, 1)
  239. if err != nil {
  240. log.Info("err,err=v%", err)
  241. } else {
  242. for logEntry := list.Front(); logEntry != nil; logEntry = logEntry.Next() {
  243. commit := logEntry.Value.(*git.Commit)
  244. log.Info("commit msg=" + commit.CommitMessage + " time=" + commit.Committer.When.Format("2006-01-02 15:04:05") + " user=" + commit.Committer.Name)
  245. if _, ok := wikiMap[commit.Committer.Name]; !ok {
  246. wikiMap[commit.Committer.Name] = 1
  247. } else {
  248. wikiMap[commit.Committer.Name] += 1
  249. }
  250. }
  251. }
  252. }
  253. }
  254. }
  255. }
  256. //other user info data
  257. err = models.CounDataByDateAndReCount(wikiMap, startTime, endTime, isReCount)
  258. if err != nil {
  259. log.Error("count user info error." + err.Error())
  260. mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage)
  261. }
  262. }
  263. func TimingCountDataByDate(date string) {
  264. TimingCountDataByDateAndReCount(date, true)
  265. }
  266. func TimingCountData() {
  267. log.Info("start to time count data")
  268. currentTimeNow := time.Now()
  269. log.Info("current time:" + currentTimeNow.Format("2006-01-02 15:04:05"))
  270. startTime := currentTimeNow.AddDate(0, 0, -1).Format("2006-01-02")
  271. TimingCountDataByDateAndReCount(startTime, false)
  272. }