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.

repo_dashbord.go 19 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. package repo
  2. import (
  3. "encoding/csv"
  4. "fmt"
  5. "io/ioutil"
  6. "net/http"
  7. "net/url"
  8. "os"
  9. "path"
  10. "strconv"
  11. "time"
  12. "code.gitea.io/gitea/models"
  13. "code.gitea.io/gitea/modules/log"
  14. "code.gitea.io/gitea/modules/context"
  15. "code.gitea.io/gitea/modules/setting"
  16. )
  17. const DEFAULT_PAGE_SIZE = 10
  18. const DATE_FORMAT = "2006-01-02"
  19. type ProjectsPeriodData struct {
  20. RecordBeginTime string `json:"recordBeginTime"`
  21. LastUpdatedTime string `json:"lastUpdatedTime"`
  22. PageSize int `json:"pageSize"`
  23. TotalPage int `json:"totalPage"`
  24. TotalCount int64 `json:"totalCount"`
  25. PageRecords []*models.RepoStatistic `json:"pageRecords"`
  26. }
  27. type UserInfo struct {
  28. User string `json:"user"`
  29. Mode int `json:"mode"`
  30. PR int64 `json:"pr"`
  31. Commit int `json:"commit"`
  32. RelAvatarLink string `json:"relAvatarLink"`
  33. Email string `json:"email"`
  34. }
  35. type ProjectLatestData struct {
  36. RecordBeginTime string `json:"recordBeginTime"`
  37. LastUpdatedTime string `json:"lastUpdatedTime"`
  38. CreatTime string `json:"creatTime"`
  39. OpenI float64 `json:"openi"`
  40. Comment int64 `json:"comment"`
  41. View int64 `json:"view"`
  42. Download int64 `json:"download"`
  43. IssueClosedRatio float32 `json:"issueClosedRatio"`
  44. Impact float64 `json:"impact"`
  45. Completeness float64 `json:"completeness"`
  46. Liveness float64 `json:"liveness"`
  47. ProjectHealth float64 `json:"projectHealth"`
  48. TeamHealth float64 `json:"teamHealth"`
  49. Growth float64 `json:"growth"`
  50. Description string `json:"description"`
  51. Top10 []UserInfo `json:"top10"`
  52. }
  53. func RestoreForkNumber(ctx *context.Context) {
  54. repos, err := models.GetAllRepositories()
  55. if err != nil {
  56. log.Error("GetAllRepositories failed: %v", err.Error())
  57. return
  58. }
  59. for _, repo := range repos {
  60. models.RestoreRepoStatFork(int64(repo.NumForks), repo.ID)
  61. }
  62. ctx.JSON(http.StatusOK, struct{}{})
  63. }
  64. func GetAllProjectsPeriodStatistics(ctx *context.Context) {
  65. recordBeginTime, err := getRecordBeginTime()
  66. if err != nil {
  67. log.Error("Can not get record begin time", err)
  68. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
  69. return
  70. }
  71. beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)
  72. if err != nil {
  73. log.Error("Parameter is wrong", err)
  74. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong"))
  75. return
  76. }
  77. q := ctx.QueryTrim("q")
  78. page := ctx.QueryInt("page")
  79. if page <= 0 {
  80. page = 1
  81. }
  82. pageSize := ctx.QueryInt("pagesize")
  83. if pageSize <= 0 {
  84. pageSize = DEFAULT_PAGE_SIZE
  85. }
  86. orderBy := getOrderBy(ctx)
  87. latestUpdatedTime, latestDate, err := models.GetRepoStatLastUpdatedTime()
  88. if err != nil {
  89. log.Error("Can not query the last updated time.", err)
  90. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error"))
  91. return
  92. }
  93. countSql := generateCountSql(beginTime, endTime, latestDate, q)
  94. total, err := models.CountRepoStatByRawSql(countSql)
  95. if err != nil {
  96. log.Error("Can not query total count.", err)
  97. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.total_count_get_error"))
  98. return
  99. }
  100. sql := generateSqlByType(ctx, beginTime, endTime, latestDate, q, orderBy, page, pageSize)
  101. projectsPeriodData := ProjectsPeriodData{
  102. RecordBeginTime: recordBeginTime.Format(DATE_FORMAT),
  103. PageSize: pageSize,
  104. TotalPage: getTotalPage(total, pageSize),
  105. TotalCount: total,
  106. LastUpdatedTime: latestUpdatedTime,
  107. PageRecords: models.GetRepoStatisticByRawSql(sql),
  108. }
  109. ctx.JSON(http.StatusOK, projectsPeriodData)
  110. }
  111. func generateSqlByType(ctx *context.Context, beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string {
  112. sql := ""
  113. if ctx.QueryTrim("type") == "all" {
  114. sql = generateTypeAllSql(beginTime, endTime, latestDate, q, orderBy, page, pageSize)
  115. } else {
  116. sql = generatePageSql(beginTime, endTime, latestDate, q, orderBy, page, pageSize)
  117. }
  118. return sql
  119. }
  120. func ServeAllProjectsPeriodStatisticsFile(ctx *context.Context) {
  121. recordBeginTime, err := getRecordBeginTime()
  122. if err != nil {
  123. log.Error("Can not get record begin time", err)
  124. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
  125. return
  126. }
  127. beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)
  128. if err != nil {
  129. log.Error("Parameter is wrong", err)
  130. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.parameter_is_wrong"))
  131. return
  132. }
  133. q := ctx.QueryTrim("q")
  134. page := ctx.QueryInt("page")
  135. if page <= 0 {
  136. page = 1
  137. }
  138. pageSize := 1000
  139. orderBy := getOrderBy(ctx)
  140. _, latestDate, err := models.GetRepoStatLastUpdatedTime()
  141. if err != nil {
  142. log.Error("Can not query the last updated time.", err)
  143. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.last_update_time_error"))
  144. return
  145. }
  146. countSql := generateCountSql(beginTime, endTime, latestDate, q)
  147. total, err := models.CountRepoStatByRawSql(countSql)
  148. if err != nil {
  149. log.Error("Can not query total count.", err)
  150. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.total_count_get_error"))
  151. return
  152. }
  153. fileName, frontName := getFileName(ctx, beginTime, endTime)
  154. if err := os.MkdirAll(setting.RadarMap.Path, os.ModePerm); err != nil {
  155. ctx.Error(http.StatusBadRequest, fmt.Errorf("Failed to create dir %s: %v", setting.AvatarUploadPath, err).Error())
  156. }
  157. totalPage := getTotalPage(total, pageSize)
  158. f, e := os.Create(fileName)
  159. defer f.Close()
  160. if e != nil {
  161. log.Warn("Failed to create file", e)
  162. }
  163. writer := csv.NewWriter(f)
  164. writer.Write(allProjectsPeroidHeader(ctx))
  165. for i := 0; i <= totalPage; i++ {
  166. pageRecords := models.GetRepoStatisticByRawSql(generateSqlByType(ctx, beginTime, endTime, latestDate, q, orderBy, i+1, pageSize))
  167. for _, record := range pageRecords {
  168. e = writer.Write(allProjectsPeroidValues(record, ctx))
  169. if e != nil {
  170. log.Warn("Failed to write record", e)
  171. }
  172. }
  173. writer.Flush()
  174. }
  175. ctx.ServeFile(fileName, url.QueryEscape(frontName))
  176. }
  177. func getFileName(ctx *context.Context, beginTime time.Time, endTime time.Time) (string, string) {
  178. baseName := setting.RadarMap.Path + "/项目分析_"
  179. if ctx.QueryTrim("q") != "" {
  180. baseName = baseName + ctx.QueryTrim("q") + "_"
  181. }
  182. if ctx.QueryTrim("type") == "all" {
  183. baseName = baseName + "所有"
  184. } else {
  185. baseName = baseName + beginTime.AddDate(0, 0, -1).Format(DATE_FORMAT) + "_" + endTime.AddDate(0, 0, -1).Format(DATE_FORMAT)
  186. }
  187. frontName := baseName + ".csv"
  188. localName := baseName + "_" + strconv.FormatInt(time.Now().Unix(), 10) + ".csv"
  189. return localName, path.Base(frontName)
  190. }
  191. func ClearUnusedStatisticsFile() {
  192. fileInfos, err := ioutil.ReadDir(setting.RadarMap.Path)
  193. if err != nil {
  194. log.Warn("can not read dir: "+setting.RadarMap.Path, err)
  195. return
  196. }
  197. for _, fileInfo := range fileInfos {
  198. if !fileInfo.IsDir() && fileInfo.ModTime().Before(time.Now().AddDate(0, 0, -1)) {
  199. os.Remove(path.Join(setting.RadarMap.Path, fileInfo.Name()))
  200. }
  201. }
  202. }
  203. func allProjectsPeroidHeader(ctx *context.Context) []string {
  204. return []string{ctx.Tr("admin.repos.id"), ctx.Tr("admin.repos.projectName"), ctx.Tr("admin.repos.isPrivate"), ctx.Tr("admin.repos.openi"), ctx.Tr("admin.repos.visit"), ctx.Tr("admin.repos.download"), ctx.Tr("admin.repos.pr"), ctx.Tr("admin.repos.commit"),
  205. ctx.Tr("admin.repos.watches"), ctx.Tr("admin.repos.stars"), ctx.Tr("admin.repos.forks"), ctx.Tr("admin.repos.issues"), ctx.Tr("admin.repos.closedIssues"), ctx.Tr("admin.repos.contributor")}
  206. }
  207. func allProjectsPeroidValues(rs *models.RepoStatistic, ctx *context.Context) []string {
  208. return []string{strconv.FormatInt(rs.RepoID, 10), constructDistinctName(rs), getIsPrivateDisplay(rs.IsPrivate, ctx), strconv.FormatFloat(rs.RadarTotal, 'f', 2, 64),
  209. strconv.FormatInt(rs.NumVisits, 10), strconv.FormatInt(rs.NumDownloads, 10), strconv.FormatInt(rs.NumPulls, 10), strconv.FormatInt(rs.NumCommits, 10),
  210. strconv.FormatInt(rs.NumWatches, 10), strconv.FormatInt(rs.NumStars, 10), strconv.FormatInt(rs.NumForks, 10), strconv.FormatInt(rs.NumIssues, 10),
  211. strconv.FormatInt(rs.NumClosedIssues, 10), strconv.FormatInt(rs.NumContributor, 10),
  212. }
  213. }
  214. func constructDistinctName(rs *models.RepoStatistic) string {
  215. if rs.OwnerName == "" {
  216. return rs.Name
  217. }
  218. return rs.OwnerName + "/" + rs.Name
  219. }
  220. func getIsPrivateDisplay(private bool, ctx *context.Context) string {
  221. if private {
  222. return ctx.Tr("admin.repos.yes")
  223. } else {
  224. return ctx.Tr("admin.repos.no")
  225. }
  226. }
  227. func GetProjectLatestStatistics(ctx *context.Context) {
  228. repoId := ctx.Params(":id")
  229. recordBeginTime, err := getRecordBeginTime()
  230. if err != nil {
  231. log.Error("Can not get record begin time", err)
  232. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
  233. return
  234. }
  235. latestUpdatedTime, latestDate, err := models.GetRepoStatLastUpdatedTime(repoId)
  236. repoIdInt, _ := strconv.ParseInt(repoId, 10, 64)
  237. repoStat, err := models.GetRepoStatisticByDateAndRepoId(latestDate, repoIdInt)
  238. if err != nil {
  239. log.Error("Can not get the repo statistics "+repoId, err)
  240. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.get_repo_stat_error"))
  241. return
  242. }
  243. repository, err := models.GetRepositoryByID(repoIdInt)
  244. if err != nil {
  245. log.Error("Can not get the repo info "+repoId, err)
  246. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.get_repo_info_error"))
  247. return
  248. }
  249. projectLatestData := ProjectLatestData{
  250. RecordBeginTime: recordBeginTime.Format(DATE_FORMAT),
  251. CreatTime: time.Unix(int64(repository.CreatedUnix), 0).Format(DATE_FORMAT),
  252. LastUpdatedTime: latestUpdatedTime,
  253. OpenI: repoStat.RadarTotal,
  254. Comment: repoStat.NumComments,
  255. View: repoStat.NumVisits,
  256. Download: repoStat.NumDownloads,
  257. IssueClosedRatio: repoStat.IssueFixedRate,
  258. Impact: repoStat.Impact,
  259. Completeness: repoStat.Completeness,
  260. Liveness: repoStat.Liveness,
  261. ProjectHealth: repoStat.ProjectHealth,
  262. TeamHealth: repoStat.TeamHealth,
  263. Growth: repoStat.Growth,
  264. Description: repository.Description,
  265. }
  266. contributors, err := models.GetTop10Contributor(repository.RepoPath())
  267. if err != nil {
  268. log.Error("can not get contributors", err)
  269. }
  270. users := make([]UserInfo, 0)
  271. for _, contributor := range contributors {
  272. mode := repository.GetCollaboratorMode(contributor.UserId)
  273. if mode == -1 {
  274. if contributor.IsAdmin {
  275. mode = int(models.AccessModeAdmin)
  276. }
  277. if contributor.UserId == repository.OwnerID {
  278. mode = int(models.AccessModeOwner)
  279. }
  280. }
  281. pr := models.GetPullCountByUserAndRepoId(repoIdInt, contributor.UserId)
  282. userInfo := UserInfo{
  283. User: contributor.Committer,
  284. Commit: contributor.CommitCnt,
  285. Mode: mode,
  286. PR: pr,
  287. RelAvatarLink: contributor.RelAvatarLink,
  288. }
  289. users = append(users, userInfo)
  290. }
  291. projectLatestData.Top10 = users
  292. ctx.JSON(http.StatusOK, projectLatestData)
  293. }
  294. func GetProjectPeriodStatistics(ctx *context.Context) {
  295. repoId := ctx.Params(":id")
  296. recordBeginTime, err := getRecordBeginTime()
  297. if err != nil {
  298. log.Error("Can not get record begin time", err)
  299. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
  300. return
  301. }
  302. repoIdInt, _ := strconv.ParseInt(repoId, 10, 64)
  303. if err != nil {
  304. log.Error("Can not get record begin time", err)
  305. ctx.Error(http.StatusBadRequest, ctx.Tr("repo.record_begintime_get_err"))
  306. return
  307. }
  308. beginTime, endTime, err := getTimePeroid(ctx, recordBeginTime)
  309. isOpenI := ctx.QueryBool("openi")
  310. var repositorys []*models.RepoStatistic
  311. if isOpenI {
  312. repositorys = models.GetRepoStatisticByRawSql(generateRadarSql(beginTime, endTime, repoIdInt))
  313. } else {
  314. repositorys = models.GetRepoStatisticByRawSql(generateTargetSql(beginTime, endTime, repoIdInt))
  315. }
  316. ctx.JSON(http.StatusOK, repositorys)
  317. }
  318. func generateRadarSql(beginTime time.Time, endTime time.Time, repoId int64) string {
  319. sql := "SELECT date, impact, completeness, liveness, project_health, team_health, growth, radar_total FROM repo_statistic" +
  320. " where repo_id=" + strconv.FormatInt(repoId, 10) + " and created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
  321. " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)
  322. return sql
  323. }
  324. func generateTargetSql(beginTime time.Time, endTime time.Time, repoId int64) string {
  325. sql := "SELECT date, num_visits,num_downloads,num_commits FROM repo_statistic" +
  326. " where repo_id=" + strconv.FormatInt(repoId, 10) + " and created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
  327. " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10)
  328. return sql
  329. }
  330. func generateCountSql(beginTime time.Time, endTime time.Time, latestDate string, q string) string {
  331. countSql := "SELECT count(*) FROM " +
  332. "(SELECT repo_id FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
  333. " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," +
  334. "(SELECT repo_id,name,is_private,radar_total from public.repo_statistic where date='" + latestDate + "') B" +
  335. " where A.repo_id=B.repo_id"
  336. if q != "" {
  337. countSql = countSql + " and B.name like '%" + q + "%'"
  338. }
  339. return countSql
  340. }
  341. func generateTypeAllSql(beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string {
  342. sql := "SELECT A.repo_id,name,owner_name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " +
  343. "(SELECT repo_id,sum(num_visits) as num_visits " +
  344. " FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
  345. " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," +
  346. "(SELECT repo_id,name,owner_name,is_private,radar_total,num_watches,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor from public.repo_statistic where date='" + latestDate + "') B" +
  347. " where A.repo_id=B.repo_id"
  348. if q != "" {
  349. sql = sql + " and name like '%" + q + "%'"
  350. }
  351. sql = sql + " order by " + orderBy + " desc,repo_id" + " limit " + strconv.Itoa(pageSize) + " offset " + strconv.Itoa((page-1)*pageSize)
  352. return sql
  353. }
  354. func generatePageSql(beginTime time.Time, endTime time.Time, latestDate string, q string, orderBy string, page int, pageSize int) string {
  355. sql := "SELECT A.repo_id,name,owner_name,is_private,radar_total,num_watches,num_visits,num_downloads,num_pulls,num_commits,num_stars,num_forks,num_issues,num_closed_issues,num_contributor FROM " +
  356. "(SELECT repo_id,sum(num_watches_added) as num_watches,sum(num_visits) as num_visits, sum(num_downloads_added) as num_downloads,sum(num_pulls_added) as num_pulls,sum(num_commits_added) as num_commits,sum(num_stars_added) as num_stars,sum(num_forks_added) num_forks,sum(num_issues_added) as num_issues,sum(num_closed_issues_added) as num_closed_issues,sum(num_contributor_added) as num_contributor " +
  357. " FROM repo_statistic where created_unix >=" + strconv.FormatInt(beginTime.Unix(), 10) +
  358. " and created_unix<" + strconv.FormatInt(endTime.Unix(), 10) + " group by repo_id) A," +
  359. "(SELECT repo_id,name,owner_name,is_private,radar_total from public.repo_statistic where date='" + latestDate + "') B" +
  360. " where A.repo_id=B.repo_id"
  361. if q != "" {
  362. sql = sql + " and B.name like '%" + q + "%'"
  363. }
  364. sql = sql + " order by " + orderBy + " desc,A.repo_id" + " limit " + strconv.Itoa(pageSize) + " offset " + strconv.Itoa((page-1)*pageSize)
  365. return sql
  366. }
  367. func getOrderBy(ctx *context.Context) string {
  368. orderBy := ""
  369. switch ctx.Query("sort") {
  370. case "openi":
  371. orderBy = "B.radar_total"
  372. case "view":
  373. orderBy = "A.num_visits"
  374. case "download":
  375. orderBy = "A.num_downloads"
  376. case "pr":
  377. orderBy = "A.num_pulls"
  378. case "commit":
  379. orderBy = "A.num_commits"
  380. case "watch":
  381. orderBy = "A.num_watches"
  382. case "star":
  383. orderBy = "A.num_stars"
  384. case "fork":
  385. orderBy = "A.num_forks"
  386. case "issue":
  387. orderBy = "A.num_issues"
  388. case "issue_closed":
  389. orderBy = "A.num_closed_issues"
  390. case "contributor":
  391. orderBy = "A.num_contributor"
  392. default:
  393. orderBy = "B.radar_total"
  394. }
  395. return orderBy
  396. }
  397. func getTimePeroid(ctx *context.Context, recordBeginTime time.Time) (time.Time, time.Time, error) {
  398. queryType := ctx.QueryTrim("type")
  399. now := time.Now()
  400. recordBeginTimeTemp := recordBeginTime.AddDate(0, 0, 1)
  401. beginTimeStr := ctx.QueryTrim("beginTime")
  402. endTimeStr := ctx.QueryTrim("endTime")
  403. var beginTime time.Time
  404. var endTime time.Time
  405. var err error
  406. if queryType != "" {
  407. if queryType == "all" {
  408. beginTime = recordBeginTimeTemp
  409. endTime = now
  410. } else if queryType == "yesterday" {
  411. endTime = now
  412. beginTime = time.Date(endTime.Year(), endTime.Month(), endTime.Day(), 0, 0, 0, 0, now.Location())
  413. } else if queryType == "current_week" {
  414. beginTime = now.AddDate(0, 0, -int(time.Now().Weekday())+2) //begin from monday
  415. beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location())
  416. endTime = now
  417. } else if queryType == "current_month" {
  418. endTime = now
  419. beginTime = time.Date(endTime.Year(), endTime.Month(), 2, 0, 0, 0, 0, now.Location())
  420. } else if queryType == "monthly" {
  421. endTime = now
  422. beginTime = now.AddDate(0, -1, 1)
  423. beginTime = time.Date(beginTime.Year(), beginTime.Month(), beginTime.Day(), 0, 0, 0, 0, now.Location())
  424. } else if queryType == "current_year" {
  425. endTime = now
  426. beginTime = time.Date(endTime.Year(), 1, 2, 0, 0, 0, 0, now.Location())
  427. } else if queryType == "last_month" {
  428. lastMonthTime := now.AddDate(0, -1, 0)
  429. beginTime = time.Date(lastMonthTime.Year(), lastMonthTime.Month(), 2, 0, 0, 0, 0, now.Location())
  430. endTime = time.Date(now.Year(), now.Month(), 2, 0, 0, 0, 0, now.Location())
  431. } else {
  432. return now, now, fmt.Errorf("The value of type parameter is wrong.")
  433. }
  434. } else {
  435. if beginTimeStr == "" || endTimeStr == "" {
  436. //如果查询类型和开始时间结束时间都未设置,按queryType=all处理
  437. beginTime = recordBeginTimeTemp
  438. endTime = now
  439. } else {
  440. beginTime, err = time.Parse("2006-01-02", beginTimeStr)
  441. if err != nil {
  442. return now, now, err
  443. }
  444. endTime, err = time.Parse("2006-01-02", endTimeStr)
  445. if err != nil {
  446. return now, now, err
  447. }
  448. beginTime = beginTime.AddDate(0, 0, 1)
  449. endTime = endTime.AddDate(0, 0, 1)
  450. }
  451. }
  452. if beginTime.Before(recordBeginTimeTemp) {
  453. beginTime = recordBeginTimeTemp
  454. }
  455. return beginTime, endTime, nil
  456. }
  457. func getRecordBeginTime() (time.Time, error) {
  458. return time.Parse(DATE_FORMAT, setting.RadarMap.RecordBeginTime)
  459. }
  460. func getTotalPage(total int64, pageSize int) int {
  461. another := 0
  462. if int(total)%pageSize != 0 {
  463. another = 1
  464. }
  465. return int(total)/pageSize + another
  466. }