| @@ -7,7 +7,6 @@ import ( | |||
| "time" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "code.gitea.io/gitea/modules/timeutil" | |||
| "xorm.io/builder" | |||
| ) | |||
| @@ -23,7 +22,7 @@ type UserBusinessAnalysis struct { | |||
| //action :ActionCommitRepo // 5 | |||
| CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //action :ActionCommentIssue // 10 | |||
| //action :ActionCreateIssue // 10 | |||
| IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||
| //comment table current date | |||
| @@ -160,10 +159,10 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| ) | |||
| } | |||
| cond = cond.And( | |||
| builder.Gte{"count_date": fmt.Sprint(pageStartTime)}, | |||
| builder.Gte{"count_date": pageStartTime.Unix()}, | |||
| ) | |||
| cond = cond.And( | |||
| builder.Lte{"count_date": fmt.Sprint(pageEndTime)}, | |||
| builder.Lte{"count_date": pageEndTime.Unix()}, | |||
| ) | |||
| count, err := statictisSess.Where(cond).Count(new(UserBusinessAnalysis)) | |||
| @@ -183,7 +182,7 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| } | |||
| statictisSess.OrderBy("count_date desc") | |||
| userBusinessAnalysisList := make([]*UserBusinessAnalysis, 0, setting.UI.IssuePagingNum) | |||
| userBusinessAnalysisList := make([]*UserBusinessAnalysis, 0) | |||
| if err := statictisSess.Table("user_business_analysis").Where(cond). | |||
| Find(&userBusinessAnalysisList); err != nil { | |||
| return nil, 0 | |||
| @@ -191,27 +190,29 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| resultMap := make(map[int64]*UserBusinessAnalysis) | |||
| var newAndCond = builder.NewCond() | |||
| var newOrCond = builder.NewCond() | |||
| for _, userRecord := range userBusinessAnalysisList { | |||
| newOrCond.Or( | |||
| builder.Eq{"id": userRecord.ID}, | |||
| if opts.Page >= 0 && opts.PageSize > 0 { | |||
| var newAndCond = builder.NewCond() | |||
| var newOrCond = builder.NewCond() | |||
| for _, userRecord := range userBusinessAnalysisList { | |||
| newOrCond = newOrCond.Or( | |||
| builder.Eq{"id": userRecord.ID}, | |||
| ) | |||
| } | |||
| newAndCond = newAndCond.And( | |||
| newOrCond, | |||
| ) | |||
| newAndCond = newAndCond.And( | |||
| builder.Gte{"count_date": opts.StartTime}, | |||
| ) | |||
| newAndCond = newAndCond.And( | |||
| builder.Lte{"count_date": opts.EndTime}, | |||
| ) | |||
| } | |||
| newAndCond = newAndCond.And( | |||
| newOrCond, | |||
| ) | |||
| newAndCond = newAndCond.And( | |||
| builder.Gte{"count_date": fmt.Sprint(opts.StartTime)}, | |||
| ) | |||
| newAndCond = newAndCond.And( | |||
| builder.Lte{"count_date": fmt.Sprint(opts.EndTime)}, | |||
| ) | |||
| userBusinessAnalysisList = make([]*UserBusinessAnalysis, 0) | |||
| if err := statictisSess.Table("user_business_analysis").Where(newAndCond). | |||
| Find(&userBusinessAnalysisList); err != nil { | |||
| return nil, 0 | |||
| userBusinessAnalysisList = make([]*UserBusinessAnalysis, 0) | |||
| if err := statictisSess.Table("user_business_analysis").Where(newAndCond). | |||
| Find(&userBusinessAnalysisList); err != nil { | |||
| return nil, 0 | |||
| } | |||
| } | |||
| log.Info("query result size=" + fmt.Sprint(len(userBusinessAnalysisList))) | |||
| @@ -245,7 +246,8 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||
| return userBusinessAnalysisReturnList, count | |||
| } | |||
| func CounDataByDate(wikiCountMap map[string]int, startTime time.Time, endTime time.Time) { | |||
| func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, endTime time.Time, isReCount bool) { | |||
| log.Info("start to count other user info data") | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| @@ -263,12 +265,15 @@ func CounDataByDate(wikiCountMap map[string]int, startTime time.Time, endTime ti | |||
| //endTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, currentTimeNow.Location()) | |||
| end_unix := endTime.Unix() | |||
| CountDate := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 1, 0, 0, currentTimeNow.Location()) | |||
| if isReCount { | |||
| CountDate = time.Date(startTime.Year(), startTime.Month(), startTime.Day(), 0, 1, 0, 0, currentTimeNow.Location()) | |||
| } | |||
| DataDate := startTime.Format("2006-01-02") | |||
| CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | |||
| CommitCountMap := queryAction(start_unix, end_unix, 5) | |||
| IssueCountMap := queryAction(start_unix, end_unix, 10) | |||
| IssueCountMap := queryAction(start_unix, end_unix, 6) | |||
| CommentCountMap := queryComment(start_unix, end_unix) | |||
| FocusRepoCountMap := queryWatch(start_unix, end_unix) | |||
| @@ -394,6 +399,10 @@ func CounDataByDate(wikiCountMap map[string]int, startTime time.Time, endTime ti | |||
| } | |||
| func CounDataByDate(wikiCountMap map[string]int, startTime time.Time, endTime time.Time) { | |||
| CounDataByDateAndReCount(wikiCountMap, startTime, endTime, false) | |||
| } | |||
| func querySolveIssue(start_unix int64, end_unix int64) map[int64]int { | |||
| //select issue_assignees.* from issue_assignees,issue where issue.is_closed=true and issue.id=issue_assignees.issue_id | |||
| sess := x.NewSession() | |||
| @@ -665,5 +674,8 @@ func subMonth(t1, t2 time.Time) (month int) { | |||
| } | |||
| monthInterval %= 12 | |||
| month = yearInterval*12 + monthInterval | |||
| if month == 0 { | |||
| month = 1 | |||
| } | |||
| return month | |||
| } | |||
| @@ -402,6 +402,26 @@ form.name_reserved = The username '%s' is reserved. | |||
| form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username. | |||
| form.name_chars_not_allowed = User name '%s' contains invalid characters. | |||
| static.sheetname=User Analysis | |||
| static.id=ID | |||
| static.name=User Name | |||
| static.codemergecount=PR Count | |||
| static.commitcount=Commit Count | |||
| static.issuecount=Issue Count | |||
| static.commentcount=Comment Count | |||
| static.focusrepocount=Focus Repo Count | |||
| static.starrepocount=Repo Star Count | |||
| static.logincount=Login Count | |||
| static.watchedcount=Watched Count | |||
| static.commitcodesize=Commit Code Line | |||
| static.solveissuecount=Solve Issue Count | |||
| static.encyclopediascount=Encyclopedias Count | |||
| static.createrepocount=Create Repo Count | |||
| static.openiindex=OpenI Index | |||
| static.registdate=Regist Date | |||
| static.countdate=Count Date | |||
| [settings] | |||
| profile = Profile | |||
| account = Account | |||
| @@ -405,6 +405,24 @@ form.name_reserved='%s' 用户名被保留。 | |||
| form.name_pattern_not_allowed=用户名中不允许使用 "%s"。 | |||
| form.name_chars_not_allowed=用户名 '%s' 包含无效字符。 | |||
| static.sheetname=用户分析 | |||
| static.id=ID | |||
| static.name=用户名 | |||
| static.codemergecount=PR数 | |||
| static.commitcount=commit次数 | |||
| static.issuecount=提出任务数 | |||
| static.commentcount=评论数 | |||
| static.focusrepocount=关注项目数 | |||
| static.starrepocount=点赞项目数 | |||
| static.logincount=登录次数 | |||
| static.watchedcount=关注者数 | |||
| static.commitcodesize=commit代码行数 | |||
| static.solveissuecount=已解决任务数 | |||
| static.encyclopediascount=百科页面贡献次数 | |||
| static.createrepocount=创建项目数 | |||
| static.openiindex=OpenI指数 | |||
| static.registdate=用户注册时间 | |||
| static.countdate=系统统计时间 | |||
| [settings] | |||
| profile=个人信息 | |||
| account=账号 | |||
| @@ -3,6 +3,8 @@ package repo | |||
| import ( | |||
| "fmt" | |||
| "net/http" | |||
| "net/url" | |||
| "strings" | |||
| "time" | |||
| "code.gitea.io/gitea/models" | |||
| @@ -10,6 +12,7 @@ import ( | |||
| "code.gitea.io/gitea/modules/git" | |||
| "code.gitea.io/gitea/modules/log" | |||
| "code.gitea.io/gitea/modules/setting" | |||
| "github.com/360EntSecGroup-Skylar/excelize/v2" | |||
| ) | |||
| func QueryUserStaticData(ctx *context.Context) { | |||
| @@ -35,6 +38,7 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| pageSize = setting.UI.IssuePagingNum | |||
| } | |||
| userName := ctx.Query("userName") | |||
| IsReturnFile := ctx.QueryBool("IsReturnFile") | |||
| log.Info("startDate=" + startDate + " endDate=" + endDate + " userName=" + userName + " page=" + fmt.Sprint(page)) | |||
| startTime, _ := time.Parse("2006-01-02", startDate) | |||
| @@ -42,6 +46,11 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| endTime = endTime.AddDate(0, 0, 1) | |||
| log.Info("startTime=" + fmt.Sprint(startTime.Unix()) + " endDate=" + fmt.Sprint(endTime.Unix())) | |||
| if IsReturnFile { | |||
| page = -1 | |||
| pageSize = -1 | |||
| } | |||
| pageOpts := &models.UserBusinessAnalysisQueryOptions{ | |||
| ListOptions: models.ListOptions{ | |||
| Page: page, | |||
| @@ -55,11 +64,76 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||
| re, count := models.QueryUserStaticDataPage(pageOpts) | |||
| mapInterface["data"] = re | |||
| mapInterface["count"] = count | |||
| ctx.JSON(http.StatusOK, mapInterface) | |||
| } | |||
| if IsReturnFile { | |||
| //writer exec file. | |||
| xlsx := excelize.NewFile() | |||
| sheetName := ctx.Tr("user.static.sheetname") | |||
| index := xlsx.NewSheet(sheetName) | |||
| dataHeader := map[string]string{ | |||
| "A1": ctx.Tr("user.static.id"), | |||
| "B1": ctx.Tr("user.static.name"), | |||
| "C1": ctx.Tr("user.static.codemergecount"), | |||
| "D1": ctx.Tr("user.static.commitcount"), | |||
| "E1": ctx.Tr("user.static.issuecount"), | |||
| "F1": ctx.Tr("user.static.commentcount"), | |||
| "G1": ctx.Tr("user.static.focusrepocount"), | |||
| "H1": ctx.Tr("user.static.starrepocount"), | |||
| "I1": ctx.Tr("user.static.logincount"), | |||
| "J1": ctx.Tr("user.static.watchedcount"), | |||
| "K1": ctx.Tr("user.static.commitcodesize"), | |||
| "L1": ctx.Tr("user.static.solveissuecount"), | |||
| "M1": ctx.Tr("user.static.encyclopediascount"), | |||
| "N1": ctx.Tr("user.static.createrepocount"), | |||
| "O1": ctx.Tr("user.static.openiindex"), | |||
| "P1": ctx.Tr("user.static.registdate"), | |||
| "Q1": ctx.Tr("user.static.countdate"), | |||
| } | |||
| for k, v := range dataHeader { | |||
| //设置单元格的值 | |||
| xlsx.SetCellValue(sheetName, k, v) | |||
| } | |||
| func TimingCountDataByDate(date string) { | |||
| for i, userRecord := range re { | |||
| rows := fmt.Sprint(i + 2) | |||
| xlsx.SetCellValue(sheetName, "A"+rows, userRecord.ID) | |||
| xlsx.SetCellValue(sheetName, "B"+rows, userRecord.Name) | |||
| xlsx.SetCellValue(sheetName, "C"+rows, userRecord.CodeMergeCount) | |||
| xlsx.SetCellValue(sheetName, "D"+rows, userRecord.CommitCount) | |||
| xlsx.SetCellValue(sheetName, "E"+rows, userRecord.IssueCount) | |||
| xlsx.SetCellValue(sheetName, "F"+rows, userRecord.CommentCount) | |||
| xlsx.SetCellValue(sheetName, "G"+rows, userRecord.FocusRepoCount) | |||
| xlsx.SetCellValue(sheetName, "H"+rows, userRecord.StarRepoCount) | |||
| xlsx.SetCellValue(sheetName, "I"+rows, userRecord.LoginCount) | |||
| xlsx.SetCellValue(sheetName, "J"+rows, userRecord.WatchedCount) | |||
| xlsx.SetCellValue(sheetName, "K"+rows, userRecord.CommitCodeSize) | |||
| xlsx.SetCellValue(sheetName, "L"+rows, userRecord.SolveIssueCount) | |||
| xlsx.SetCellValue(sheetName, "M"+rows, userRecord.EncyclopediasCount) | |||
| xlsx.SetCellValue(sheetName, "N"+rows, userRecord.CreateRepoCount) | |||
| xlsx.SetCellValue(sheetName, "O"+rows, userRecord.OpenIIndex) | |||
| xlsx.SetCellValue(sheetName, "P"+rows, userRecord.RegistDate.Format("2006-01-02")) | |||
| xlsx.SetCellValue(sheetName, "Q"+rows, time.Unix(userRecord.CountDate, 0).Format("2006-01-02")) | |||
| } | |||
| //设置默认打开的表单 | |||
| xlsx.SetActiveSheet(index) | |||
| filename := sheetName + "_" + strings.ReplaceAll(startDate, "-", "") + "_" + strings.ReplaceAll(endDate, "-", "") + ".xlsx" | |||
| if len(userName) > 0 { | |||
| filename = sheetName + "_" + userName + "_" + strings.ReplaceAll(startDate, "-", "") + "_" + strings.ReplaceAll(endDate, "-", "") + ".xlsx" | |||
| } | |||
| ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(filename)) | |||
| ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||
| if _, err := xlsx.WriteTo(ctx.Resp); err != nil { | |||
| log.Info("writer exel error." + err.Error()) | |||
| } | |||
| } else { | |||
| ctx.JSON(http.StatusOK, mapInterface) | |||
| } | |||
| } | |||
| func TimingCountDataByDateAndReCount(date string, isReCount bool) { | |||
| t, _ := time.Parse("2006-01-02", date) | |||
| startTime := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | |||
| @@ -106,16 +180,17 @@ func TimingCountDataByDate(date string) { | |||
| } | |||
| } | |||
| //other user info data | |||
| models.CounDataByDate(wikiMap, startTime, endTime) | |||
| models.CounDataByDateAndReCount(wikiMap, startTime, endTime, isReCount) | |||
| } | |||
| func TimingCountDataByDate(date string) { | |||
| TimingCountDataByDateAndReCount(date, true) | |||
| } | |||
| func TimingCountData() { | |||
| log.Info("start to time count data") | |||
| currentTimeNow := time.Now() | |||
| log.Info("current time:" + currentTimeNow.Format("2006-01-02 15:04:05")) | |||
| startTime := currentTimeNow.AddDate(0, 0, -1).Format("2006-01-02") | |||
| TimingCountDataByDate(startTime) | |||
| TimingCountDataByDateAndReCount(startTime, false) | |||
| } | |||
| @@ -37,7 +37,9 @@ | |||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{if .IsAdmin}} | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{else if .IsLandingPageHome}} | |||
| @@ -53,6 +55,9 @@ | |||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||
| {{if .IsAdmin}} | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{else if .IsLandingPageExplore}} | |||
| @@ -29,7 +29,9 @@ | |||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{if .IsAdmin}} | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{else if .IsLandingPageHome}} | |||
| @@ -45,6 +47,9 @@ | |||
| <a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||
| <a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||
| {{if .IsAdmin}} | |||
| <a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||
| {{end}} | |||
| </div> | |||
| </div> | |||
| {{else if .IsLandingPageExplore}} | |||
| @@ -2,24 +2,24 @@ | |||
| <div style="width: 100%;"> | |||
| <div id = "pro_main"> | |||
| <div style="margin-top: 10px;"> | |||
| <b class="pro_item">项目分析</b> <span class="update_time">数据更新时间:{{lastUpdatedTime}} / 从{{recordBeginTime}}开始统计</span> | |||
| <b class="pro_item">项目分析</b> <span class="update_time">数据更新时间:</span> <span style="font-size: 12px;">{{lastUpdatedTime}} / 从{{recordBeginTime}}开始统计</span> | |||
| </div> | |||
| <bar-label :width="'95%'" :height="'500px'"></bar-label> | |||
| <div style="margin-top: 20px;"> | |||
| <span class="sta_iterm">统计周期:</span> | |||
| <button type="button" class='btn' id ="yesterday" v-bind:class="{colorChange:1==dynamic}" @click="getAllProList('yesterday',1)">昨天</button> | |||
| <button type="button" class='btn' id = "current_week" v-bind:class="{colorChange:2==dynamic}" @click="getAllProList('current_week',2)">本周</button> | |||
| <button type="button" class='btn' id = "current_month" v-bind:class="{colorChange:3==dynamic}" @click="getAllProList('current_month',3)">本月</button> | |||
| <button type="button" class='btn' id = "last_month" v-bind:class="{colorChange:4==dynamic}" @click="getAllProList('last_month',4)">上月</button> | |||
| <button type="button" class='btn' id = "monthly" v-bind:class="{colorChange:5==dynamic}" @click="getAllProList('monthly',5)">近30天</button> | |||
| <button type="button" class='btn' id = "current_year" v-bind:class="{colorChange:6==dynamic}" @click="getAllProList('current_year',6)">今年</button> | |||
| <button type="button" class='btn' id = "all" v-bind:class="{colorChange:7==dynamic}" @click="getAllProList('all',7)">所有</button> | |||
| <button type="button" class='btn' id ="yesterday" v-bind:class="{colorChange:1==dynamic}" @click="resetPage(),getAllProList('yesterday',1)">昨天</button> | |||
| <button type="button" class='btn' id = "current_week" v-bind:class="{colorChange:2==dynamic}" @click="resetPage(),getAllProList('current_week',2)">本周</button> | |||
| <button type="button" class='btn' id = "current_month" v-bind:class="{colorChange:3==dynamic}" @click="resetPage(),getAllProList('current_month',3)">本月</button> | |||
| <button type="button" class='btn' id = "last_month" v-bind:class="{colorChange:4==dynamic}" @click="resetPage(),getAllProList('last_month',4)">上月</button> | |||
| <button type="button" class='btn' id = "monthly" v-bind:class="{colorChange:5==dynamic}" @click="resetPage(),getAllProList('monthly',5)">近30天</button> | |||
| <button type="button" class='btn' id = "current_year" v-bind:class="{colorChange:6==dynamic}" @click="resetPage(),getAllProList('current_year',6)">今年</button> | |||
| <button type="button" class='btn' id = "all" v-bind:class="{colorChange:7==dynamic}" @click="resetPage(),getAllProList('all',7)">所有</button> | |||
| <span style="margin-left: 20px;"> | |||
| <el-date-picker | |||
| v-model="value_time" | |||
| prefix-icon="el-icon-time" | |||
| @change="getAllProList('',0)" | |||
| @change="resetPage(),getAllProList('',0)" | |||
| type="daterange" | |||
| size='small' | |||
| range-separator="至" | |||
| @@ -35,7 +35,7 @@ | |||
| <span style="display:inline-block;margin-left: 20px; "> | |||
| <el-input size="small" placeholder="输入项目关键字搜索" v-model="search" class="input-with-select" @keyup.enter.native="searchName() "><i slot="suffix" class="el-input__icon el-icon-search"></i> | |||
| <el-input size="small" placeholder="输入项目关键字搜索" v-model="search" class="input-with-select" @keyup.enter.native="searchName() "><i slot="suffix" class="el-input__icon el-icon-search" @click="searchName() "></i> | |||
| </el-input> | |||
| </span> | |||
| </span> | |||
| @@ -53,6 +53,16 @@ | |||
| stripe | |||
| > | |||
| </el-table-column> | |||
| <el-table-column | |||
| label="拥有者" | |||
| align="center" | |||
| prop="ownerName" | |||
| stripe | |||
| v-if='0' | |||
| > | |||
| </el-table-column> | |||
| <el-table-column | |||
| label="项目名称" | |||
| width="125px" | |||
| @@ -61,7 +71,7 @@ | |||
| style="color:#0366D6 100%;" | |||
| > | |||
| <template slot-scope="scope"> | |||
| <a @click=goToDetailPage(scope.row.repo_id,scope.row.name)>{{scope.row.name}} </a> | |||
| <a @click=goToDetailPage(scope.row.repo_id,scope.row.name,scope.row.ownerName)>{{scope.row.name}} </a> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| @@ -146,7 +156,7 @@ | |||
| </div> | |||
| <div id ="pro_detail" style="display:none;width: 100%;"> | |||
| <div style="margin-top: 10px;"> | |||
| <b class="pro_item">OpenI / {{this.pro_name}}</b> <span class="update_time">数据更新时间:{{tableDataIDTotal.lastUpdatedTime}}/{{tableDataIDTotal.recordBeginTime}}</span> | |||
| <b class="pro_item">{{this.ownerName}}/{{this.pro_name}}</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{tableDataIDTotal.lastUpdatedTime}}/{{tableDataIDTotal.recordBeginTime}}</span> | |||
| </div> | |||
| <div style="margin-top: 10px;"> | |||
| 项目描述:{{tableDataIDTotal.description | discriptionFun}} | |||
| @@ -175,7 +185,7 @@ | |||
| </el-col> | |||
| <el-col :span='4' style="text-align: center;"> | |||
| <el-row>任务完成比例</el-row> | |||
| <el-row class="item_content">{{tableDataIDTotal.issueClosedRatio}}</el-row> | |||
| <el-row class="item_content">{{tableDataIDTotal.issueClosedRatio * 100}}%</el-row> | |||
| </el-col> | |||
| </el-row> | |||
| </div> | |||
| @@ -205,14 +215,19 @@ | |||
| label="用户名" | |||
| align="center" | |||
| prop="user"> | |||
| <template slot-scope="scope"> | |||
| <a v-if="scope.row.mode!=-1" :href="AppSubUrl +'../../../'+ scope.row.user"><img class="ui avatar s16 image js-popover-card" :src="scope.row.relAvatarLink">{{scope.row.user}} </a> | |||
| <a v-else :href="'mailto:'+ scope.row.email "> <img class="ui avatar s16 image js-popover-card" :avatar="scope.row.email"> {{scope.row.user}}</a> | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| label="身份" | |||
| align="center" | |||
| prop="mode"> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.mode | showMode}} | |||
| </template> | |||
| prop="mode" | |||
| v-if='0'> | |||
| <template slot-scope="scope"> | |||
| {{scope.row.mode | showMode}} | |||
| </template> | |||
| </el-table-column> | |||
| <el-table-column | |||
| prop="pr" | |||
| @@ -233,18 +248,18 @@ | |||
| </div> | |||
| <div style="margin-top: 20px;"> | |||
| <span class="sta_iterm">统计周期:</span> | |||
| <button type="button" class='btn' id ="yesterday_pro" v-bind:class="{colorChange:1==dynamic_pro}" @click="getOneProList(pro_id,'yesterday',true,1),getOneProList(pro_id,'yesterday',false,1)">昨天</button> | |||
| <button type="button" class='btn' id = "current_week_pro" v-bind:class="{colorChange:2==dynamic_pro}" @click="getOneProList(pro_id,'current_week',true,2),getOneProList(pro_id,'current_week',false,2)">本周</button> | |||
| <button type="button" class='btn' id = "current_month_pro" v-bind:class="{colorChange:3==dynamic_pro}" @click="getOneProList(pro_id,'current_month',true,3),getOneProList(pro_id,'current_month',false,3)">本月</button> | |||
| <button type="button" class='btn' id = "last_month_pro" v-bind:class="{colorChange:4==dynamic_pro}" @click="getOneProList(pro_id,'last_month',true,4),getOneProList(pro_id,'last_month',false,4)">上月</button> | |||
| <button type="button" class='btn' id = "monthly_pro" v-bind:class="{colorChange:5==dynamic_pro}" @click="getOneProList(pro_id,'monthly',true,5),getOneProList(pro_id,'monthly',false,5)">近30天</button> | |||
| <button type="button" class='btn' id = "current_year_pro" v-bind:class="{colorChange:6==dynamic}" @click="getOneProList(pro_id,'current_year',true,6),getOneProList(pro_id,'current_year',false,6)">今年</button> | |||
| <button type="button" class='btn' id = "all_pro" v-bind:class="{colorChange:7==dynamic_pro}" @click="getOneProList(pro_id,'all',true,7),getOneProList(pro_id,'all',false,7)">所有</button> | |||
| <button type="button" class='btn' id ="yesterday_pro" v-bind:class="{colorChange:1==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'yesterday',true,1),getOneProList(pro_id,'yesterday',false,1)">昨天</button> | |||
| <button type="button" class='btn' id = "current_week_pro" v-bind:class="{colorChange:2==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_week',true,2),getOneProList(pro_id,'current_week',false,2)">本周</button> | |||
| <button type="button" class='btn' id = "current_month_pro" v-bind:class="{colorChange:3==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'current_month',true,3),getOneProList(pro_id,'current_month',false,3)">本月</button> | |||
| <button type="button" class='btn' id = "last_month_pro" v-bind:class="{colorChange:4==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'last_month',true,4),getOneProList(pro_id,'last_month',false,4)">上月</button> | |||
| <button type="button" class='btn' id = "monthly_pro" v-bind:class="{colorChange:5==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'monthly',true,5),getOneProList(pro_id,'monthly',false,5)">近30天</button> | |||
| <button type="button" class='btn' id = "current_year_pro" v-bind:class="{colorChange:6==dynamic}" @click="resetCurrentPage(),getOneProList(pro_id,'current_year',true,6),getOneProList(pro_id,'current_year',false,6)">今年</button> | |||
| <button type="button" class='btn' id = "all_pro" v-bind:class="{colorChange:7==dynamic_pro}" @click="resetCurrentPage(),getOneProList(pro_id,'all',true,7),getOneProList(pro_id,'all',false,7)">所有</button> | |||
| <span style="margin-left: 20px;"> | |||
| <el-date-picker | |||
| v-model="create_time_pro" | |||
| prefix-icon="el-icon-time" | |||
| @change="getOneProList(pro_id,'',true,0),getOneProList(pro_id,'',false,0),clickCheckBox" | |||
| @change="resetCurrentPage(),getOneProList(pro_id,'',true,0),getOneProList(pro_id,'',false,0),clickCheckBox" | |||
| type="daterange" | |||
| size='small' | |||
| range-separator="至" | |||
| @@ -321,6 +336,8 @@ | |||
| <script> | |||
| // import barLabel from './basic/barLabel.vue'; | |||
| const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||
| import { export2Excel } from '../excel/util.js' | |||
| export default{ | |||
| name:'ProAnalysis', | |||
| @@ -358,6 +375,7 @@ | |||
| dynamic_pro:7, | |||
| pro_name:'', | |||
| pro_id:'', | |||
| ownerName:'', | |||
| radarOpenI:'', | |||
| echartsOITd:'', | |||
| echartsSelectData:'', | |||
| @@ -375,6 +393,7 @@ | |||
| // this.getOneProList(this.pro_id,'all',true,7) | |||
| // this.getOneProList(this.pro_id,'all',false,7) | |||
| // this.fileName() | |||
| this.currentPage=1 | |||
| var saveFileName = this.getFileName() | |||
| export2Excel(this.columns,this.tableDataID,saveFileName) | |||
| }, | |||
| @@ -458,9 +477,17 @@ | |||
| return saveFileName | |||
| }, | |||
| resetPage(){ | |||
| this.page=1 | |||
| this.params.page = 1 | |||
| }, | |||
| resetCurrentPage(){ | |||
| this.currentPage=1 | |||
| }, | |||
| handleCurrentChange(val){ | |||
| console.log(val) | |||
| this.params.page = val | |||
| this.page = val | |||
| switch(this.params.type){ | |||
| case "yesterday":{ | |||
| this.value_time='' | |||
| @@ -561,19 +588,21 @@ | |||
| }) | |||
| }, | |||
| searchName(){ | |||
| this.params.q = this.search | |||
| this.params.page = 1 | |||
| this.getAllProList("all",7) | |||
| this.params.q = this.search | |||
| this.params.page = 1 | |||
| this.page=1 | |||
| this.getAllProList(this.params.type, this.dynamic) | |||
| }, | |||
| goToDetailPage(pro_id,pro_name){ | |||
| goToDetailPage(pro_id,pro_name,ownerName){ | |||
| this.currentPage=1 | |||
| document.getElementById("pro_main").style.display="none"; | |||
| document.getElementById("pro_detail").style.display="block"; | |||
| console.log(pro_id) | |||
| console.log(pro_name) | |||
| this.pro_name=pro_name; | |||
| this.pro_id=pro_id; | |||
| this.ownerName=ownerName | |||
| this.getOneProData(pro_id); | |||
| this.getOneProList(pro_id,"monthly",true,5); | |||
| this.getOneProList(pro_id,"monthly",false,5); | |||
| @@ -723,7 +752,7 @@ | |||
| var ydata_openI=[] | |||
| for(var i =0;i<this.tableDataIDOpenI.length;i++){ | |||
| xdata_openI.push(this.tableDataIDOpenI[i].date); | |||
| ydata_openI.push(this.roundingF(this.tableDataIDOpenI[this.tableDataIDOpenI.length-1-i].openi)) | |||
| ydata_openI.push(this.roundingF(this.tableDataIDOpenI[i].openi)) | |||
| } | |||
| console.log("ydata_openI:"+ydata_openI) | |||
| console.log(xdata_openI) | |||
| @@ -810,7 +839,7 @@ | |||
| var ydata_commit=[] | |||
| // if () | |||
| for(var i =0;i<this.tableDataID.length;i++){ | |||
| xdata.push(this.tableDataID[i].date); | |||
| xdata.push(this.tableDataID[this.tableDataID.length-1-i].date); | |||
| ydata_view.push(this.roundingF(this.tableDataID[this.tableDataID.length-1-i].view)) | |||
| ydata_download.push(this.roundingF(this.tableDataID[this.tableDataID.length-1-i].download)) | |||
| ydata_commit.push(this.roundingF(this.tableDataID[this.tableDataID.length-1-i].commit)) | |||
| @@ -908,6 +937,7 @@ | |||
| // option.legend.selected = obj; | |||
| // this.echartsSelectData.setOption(option); | |||
| // }); | |||
| }, | |||
| @@ -961,7 +991,16 @@ | |||
| }else{ | |||
| return "未定义" | |||
| } | |||
| } | |||
| }, | |||
| showContext(value){ | |||
| if (value.mode!=-1){ | |||
| return " <img class=\"ui avatar image\" src= \" "+ value.RelAvatarLink+ " \" > "+" <a href= \" " + AppSubUrl+"/"+value.user+ "\">"+value.user+" </a>" | |||
| } | |||
| else{ | |||
| return " <a href=\" mailto:" + value.email + "class=\"circular ui button\">" +value.user+ "</a>" | |||
| } | |||
| }, | |||
| }, | |||
| @@ -984,6 +1023,19 @@ | |||
| // } | |||
| // console.log("this.radarOpenI:"+this.radarOpenI) | |||
| }, | |||
| watch:{ | |||
| search(val){ | |||
| if(!val){ | |||
| this.params.q = this.search | |||
| this.params.page = 1 | |||
| this.page=1 | |||
| this.getAllProList(this.params.type, this.dynamic) | |||
| } | |||
| } | |||
| }, | |||
| created() { | |||
| // this.download_a=document.getElementById("download_file") | |||
| } | |||
| @@ -1017,16 +1069,17 @@ | |||
| height: 30px; | |||
| border-radius:4px ; | |||
| } | |||
| /* | |||
| .btn:focus, | |||
| .btn:active{ | |||
| background-color:#409effd6 ; | |||
| } | |||
| } */ | |||
| /deep/ .el-date-picker { | |||
| width: 200px; | |||
| } | |||
| .colorChange { | |||
| background-color: #409effd6; | |||
| color: #FFFF; | |||
| } | |||
| .items{ | |||
| text-align: center; | |||
| @@ -1,7 +1,7 @@ | |||
| <template> | |||
| <div> | |||
| <div style="margin-top: 10px;"> | |||
| <b class="pro_item">用户分析</b> <span class="update_time">数据更新时间:{{lastUpdatedTime}}  / 从{{recordBeginTime}}开始统计</span> | |||
| <b class="pro_item">用户分析</b> <span class="update_time">数据更新时间:</span><span style="font-size: 12px;">{{lastUpdatedTime}}  / 从{{recordBeginTime}}开始统计</span> | |||
| </div> | |||
| <div style="margin-top: 20px;"> | |||
| <span class="sta_iterm">统计周期:</span> | |||
| @@ -171,7 +171,7 @@ | |||
| value_time: '', | |||
| search:'', | |||
| data:'', | |||
| columns: [{title: 'ID',key: 'ID'},{title: '用户名',key: 'Name'},{title: 'PR数',key: 'CommitCount'},{title: '提出任务数',key: 'IssueCount'},{title: '评论数',key: 'CommentCount'},{title: '关注项目数',key: 'FocusRepoCount'},{title: '点赞项目数',key: 'StarRepoCount'},{title: '登录次数',key: 'LoginCount'},{title:'关注者数',key:'WatchedCount'},{title:'commit代码行数',key:'CommitCodeSize'},{title:'已解决任务数',key:'SolveIssueCount'},{title:'百科页面贡献次数',key:'EncyclopediasCount'},{title:'创建项目',key:'CreateRepoCount'},{title:'用户注册时间',key:'RegistDate'},{title:'系统统计时间',key:'CountDate'}], | |||
| columns: [{title: 'ID',key: 'ID'},{title: '用户名',key: 'Name'},{title: 'PR数',key: 'CodeMergeCount'},{title: 'cimmit数',key:'CommitCount'},{title: '提出任务数',key: 'IssueCount'},{title: '评论数',key: 'CommentCount'},{title: '关注项目数',key: 'FocusRepoCount'},{title: '点赞项目数',key: 'StarRepoCount'},{title: '登录次数',key: 'LoginCount'},{title:'关注者数',key:'WatchedCount'},{title:'commit代码行数',key:'CommitCodeSize'},{title:'已解决任务数',key:'SolveIssueCount'},{title:'百科页面贡献次数',key:'EncyclopediasCount'},{title:'创建项目',key:'CreateRepoCount'},{title:'用户注册时间',key:'RegistDate'},{title:'系统统计时间',key:'CountDate'}], | |||
| blob:'', | |||
| fileName:'', | |||
| dynamic:7, | |||
| @@ -252,7 +252,7 @@ | |||
| var tmp = new Date(now.setTime(now.getTime()-24*60*60*1000)); | |||
| var yesterday = this.formatDate(tmp.getFullYear(),tmp.getMonth()+1,tmp.getDate()); | |||
| this.params.startDate = yesterday | |||
| this.params.endDate = today | |||
| this.params.endDate = yesterday | |||
| this.value_time=[] | |||
| // document.getElementById("yesterday_usr").style.backgroundColor="409effd6" | |||
| // document.getElementById("current_week_usr") | |||
| @@ -422,10 +422,10 @@ | |||
| border-radius:4px ; | |||
| } | |||
| .btn:focus, | |||
| /* .btn:focus, | |||
| .btn:active{ | |||
| background-color:#409effd6 ; | |||
| } | |||
| } */ | |||
| /deep/ .el-date-picker { | |||
| width: 200px; | |||
| } | |||
| @@ -435,6 +435,7 @@ | |||
| .colorChange { | |||
| background-color: #409effd6; | |||
| color: #FFFF; | |||
| } | |||
| </style> | |||