| @@ -14,13 +14,14 @@ class Admins::IdentityVerificationsController < Admins::BaseController | |||
| end | |||
| def update | |||
| if @identity_verification.update(update_params) | |||
| if update_params[:state] == "已拒绝" && update_params[:description].blank? | |||
| flash[:danger] = '拒绝理由不能为空' | |||
| render 'edit' | |||
| else | |||
| UserAction.create(action_id: @identity_verification.id, action_type: "UpdateIdentityVerifications", user_id: current_user.id, :ip => request.remote_ip, data_bank: @identity_verification.attributes.to_json) | |||
| @identity_verification.update(update_params) | |||
| redirect_to admins_identity_verifications_path | |||
| flash[:success] = "更新成功" | |||
| else | |||
| redirect_to admins_identity_verifications_path | |||
| flash[:danger] = "更新失败" | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| class Admins::IssuesRankController < Admins::BaseController | |||
| def index | |||
| @statistics = DailyProjectStatistic.where('date >= ? AND date <= ?', begin_date, end_date) | |||
| @statistics = @statistics.group(:project_id).joins(:project).select("project_id, | |||
| sum(issues) as issues, | |||
| sum(closed_issues) as closed_issues, | |||
| projects.issues_count as issues_count") | |||
| @statistics = @statistics.order("#{sort_by} #{sort_direction}").limit(50) | |||
| end | |||
| private | |||
| def begin_date | |||
| params.fetch(:begin_date, (Date.yesterday-7.days).to_s) | |||
| end | |||
| def end_date | |||
| params.fetch(:end_date, Date.yesterday.to_s) | |||
| end | |||
| def sort_by | |||
| DailyProjectStatistic.column_names.include?(params.fetch(:sort_by, "issues")) ? params.fetch(:sort_by, "issues") : "issues" | |||
| end | |||
| def sort_direction | |||
| %w(desc asc).include?(params.fetch(:sort_direction, "desc")) ? params.fetch(:sort_direction, "desc") : "desc" | |||
| end | |||
| end | |||
| @@ -17,11 +17,11 @@ class Admins::ProjectsRankController < Admins::BaseController | |||
| private | |||
| def begin_date | |||
| params.fetch(:begin_date, (Date.today-7.days).to_s) | |||
| params.fetch(:begin_date, (Date.yesterday-7.days).to_s) | |||
| end | |||
| def end_date | |||
| params.fetch(:end_date, Date.today.to_s) | |||
| params.fetch(:end_date, Date.yesterday.to_s) | |||
| end | |||
| def sort_by | |||
| @@ -13,6 +13,7 @@ class DailyProjectStatisticsJob < ApplicationJob | |||
| praises = result["praises"].to_i | |||
| forks = result["forks"].to_i | |||
| issues = result["issues"].to_i | |||
| closed_issues = result["closed_issues"].to_i | |||
| pullrequests = result["pullrequests"].to_i | |||
| commits = result["commits"].to_i | |||
| score = visits *1 + watchers *5 + praises * 5 + forks * 10 + issues *5 + pullrequests * 10 + commits * 5 | |||
| @@ -25,6 +26,7 @@ class DailyProjectStatisticsJob < ApplicationJob | |||
| praises: praises, | |||
| forks: forks, | |||
| issues: issues, | |||
| closed_issues: closed_issues, | |||
| pullrequests: pullrequests, | |||
| commits: commits | |||
| ) | |||
| @@ -2,18 +2,20 @@ | |||
| # | |||
| # Table name: daily_project_statistics | |||
| # | |||
| # id :integer not null, primary key | |||
| # project_id :integer | |||
| # date :string(255) | |||
| # visits :integer default("0") | |||
| # watchers :integer default("0") | |||
| # praises :integer default("0") | |||
| # forks :integer default("0") | |||
| # issues :integer default("0") | |||
| # pullrequests :integer default("0") | |||
| # commits :integer default("0") | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # id :integer not null, primary key | |||
| # project_id :integer | |||
| # date :date | |||
| # score :integer default("0") | |||
| # visits :integer default("0") | |||
| # watchers :integer default("0") | |||
| # praises :integer default("0") | |||
| # forks :integer default("0") | |||
| # issues :integer default("0") | |||
| # pullrequests :integer default("0") | |||
| # commits :integer default("0") | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # closed_issues :integer default("0") | |||
| # | |||
| # Indexes | |||
| # | |||
| @@ -99,9 +99,20 @@ class Issue < ApplicationRecord | |||
| scope :closed, ->{where(status_id: 5)} | |||
| scope :opened, ->{where.not(status_id: 5)} | |||
| after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic | |||
| after_save :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container | |||
| after_save :incre_or_decre_closed_issues_count, :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container | |||
| after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic | |||
| def incre_or_decre_closed_issues_count | |||
| if previous_changes[:status_id].present? | |||
| if previous_changes[:status_id][1] == 5 | |||
| CacheAsyncSetJob.perform_later("project_common_service", {closed_issues: 1}, self.project_id) | |||
| end | |||
| if previous_changes[:status_id][0] == 5 | |||
| CacheAsyncSetJob.perform_later("project_common_service", {closed_issues: -1}, self.project_id) | |||
| end | |||
| end | |||
| end | |||
| def incre_project_common | |||
| CacheAsyncSetJob.perform_later("project_common_service", {issues: 1}, self.project_id) | |||
| end | |||
| @@ -1,5 +1,5 @@ | |||
| class Cache::V2::ProjectCommonService < ApplicationService | |||
| attr_reader :project_id, :owner_id, :name, :identifier, :description, :visits, :watchers, :praises, :forks, :issues, :pullrequests, :commits | |||
| attr_reader :project_id, :owner_id, :name, :identifier, :description, :visits, :watchers, :praises, :forks, :issues, :closed_issues, :pullrequests, :commits | |||
| attr_accessor :project | |||
| def initialize(project_id, params={}) | |||
| @@ -13,6 +13,7 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| @praises = params[:praises] | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @closed_issues = params[:closed_issues] | |||
| @pullrequests = params[:pullrequests] | |||
| @commits = params[:commits] | |||
| end | |||
| @@ -78,6 +79,10 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| "issues" | |||
| end | |||
| def closed_issues_key | |||
| "closed_issues" | |||
| end | |||
| def pullrequests_key | |||
| "pullrequests" | |||
| end | |||
| @@ -151,6 +156,10 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| Cache::V2::ProjectRankService.call(@project_id, {issues: @issues}) | |||
| Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {issues: @issues}) | |||
| end | |||
| if @closed_issues.present? | |||
| $redis_cache.hincrby(project_common_key, closed_issues_key, @closed_issues) | |||
| Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {closed_issues: @closed_issues}) | |||
| end | |||
| if @pullrequests.present? | |||
| $redis_cache.hincrby(project_common_key, pullrequests_key, @pullrequests) | |||
| Cache::V2::ProjectRankService.call(@project_id, {pullrequests: @pullrequests}) | |||
| @@ -202,6 +211,10 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| $redis_cache.hset(project_common_key, issues_key, Issue.issue_issue.where(project_id: @project_id).count) | |||
| end | |||
| def reset_project_closed_issues | |||
| $redis_cache.hset(project_common_key, closed_issues_key, Issue.issue_issue.closed.where(project_id: @project_id).count) | |||
| end | |||
| def reset_project_pullrequests | |||
| $redis_cache.hset(project_common_key, pullrequests_key, PullRequest.where(project_id: @project_id).count) | |||
| end | |||
| @@ -224,6 +237,7 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| reset_project_praises | |||
| reset_project_forks | |||
| reset_project_issues | |||
| reset_project_closed_issues | |||
| reset_project_pullrequests | |||
| reset_project_commits | |||
| @@ -1,6 +1,6 @@ | |||
| # 项目日活跃度计算存储 | |||
| class Cache::V2::ProjectDateRankService < ApplicationService | |||
| attr_reader :project_id, :rank_date, :visits, :praises, :forks, :issues, :pullrequests, :commits | |||
| attr_reader :project_id, :rank_date, :visits, :praises, :forks, :issues, :closed_issues, :pullrequests, :commits | |||
| attr_accessor :project_common | |||
| def initialize(project_id, rank_date=Date.today, params={}) | |||
| @@ -11,6 +11,7 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| @praises = params[:praises] | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @closed_issues = params[:closed_issues] | |||
| @pullrequests = params[:pullrequests] | |||
| @commits = params[:commits] | |||
| end | |||
| @@ -57,6 +58,9 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 5, @project_id) | |||
| $redis_cache.hincrby(project_rank_statistic_key, "issues", @issues.to_i) | |||
| end | |||
| if @closed_issues.present? | |||
| $redis_cache.hincrby(project_rank_statistic_key, "closed_issues", @closed_issues.to_i) | |||
| end | |||
| if @pullrequests.present? | |||
| $redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id) | |||
| $redis_cache.hincrby(project_rank_statistic_key, "pullrequests", @pullrequests.to_i) | |||
| @@ -106,7 +106,7 @@ | |||
| </div> | |||
| </br> | |||
| <div class="form-row"> | |||
| <%= f.input :description, as: :text,label: '拒绝理由:(拒绝时请填写拒绝理由,可以为空)', wrapper_html: { class: 'col-md-12' }, input_html: { maxlength: 100, size: 40, class: 'col-md-11' , value: @identity_verification.description } %> | |||
| <%= f.input :description, as: :text,label: '拒绝理由:(拒绝时请填写拒绝理由,不可以为空)', wrapper_html: { class: 'col-md-12' }, input_html: { maxlength: 100, size: 40, class: 'col-md-11' , value: @identity_verification.description } %> | |||
| </div> | |||
| <div class="form-row mt-4"> | |||
| <%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %> | |||
| @@ -0,0 +1,37 @@ | |||
| <% define_admin_breadcrumbs do %> | |||
| <% add_admin_breadcrumb('项目排行榜', admins_path) %> | |||
| <% end %> | |||
| <div class="box search-form-container user-list-form"> | |||
| <%= form_tag(admins_issues_rank_index_path, method: :get, class: 'form-inline search-form flex-1', id: 'issue-rank-date-form') do %> | |||
| <div class="input-group"> | |||
| <span class="input-group-text">开始日期</span> | |||
| <input class="form-control datetimepicker" type="text" name="begin_date" value="<%= params[:begin_date] || (Date.yesterday - 7.days).to_s%>" aria-label="选择日期"> | |||
| </div> | |||
| <div class="input-group"> | |||
| <span class="input-group-text">截止日期</span> | |||
| <input class="form-control datetimepicker" type="text" name="end_date" value="<%= params[:end_date] || Date.yesterday.to_s%>" aria-label="选择日期"> | |||
| </div> | |||
| <% end %> | |||
| </div> | |||
| <div class="box admin-list-container issue-rank-list-container"> | |||
| <%= render partial: 'admins/issues_rank/shared/data_list', locals: { statistics: @statistics } %> | |||
| </div> | |||
| <script> | |||
| $(".datetimepicker").on('change', function() { | |||
| $("#issue-rank-date-form").submit() | |||
| }); | |||
| $(".datetimepicker").on('change', function() { | |||
| $("#issue-rank-date-form").submit() | |||
| }); | |||
| $('.datetimepicker').datetimepicker({ | |||
| language: 'zh-CN', // 中文语言包 | |||
| autoclose: 1, // 选中日期后自动关闭 | |||
| format: 'yyyy-mm-dd', // 日期格式 | |||
| minView: "month", // 最小日期显示单元,这里最小显示月份界面,即可以选择到日 | |||
| todayBtn: 1, // 显示今天按钮 | |||
| todayHighlight: 1, // 显示今天高亮 | |||
| }); | |||
| </script> | |||
| @@ -0,0 +1 @@ | |||
| $('.issue-rank-list-container').html("<%= j( render partial: 'admins/issues_rank/shared/data_list', locals: { statistics: @statistics } ) %>"); | |||
| @@ -0,0 +1,26 @@ | |||
| <table class="table table-hover text-center subject-list-table"> | |||
| <thead class="thead-light"> | |||
| <tr> | |||
| <th width="20%">排名</th> | |||
| <th width="20%">项目</th> | |||
| <th width="20%">新增疑修数</th> | |||
| <th width="20%">关闭疑修数</th> | |||
| <th width="20%">当前疑修数量</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <% statistics.each_with_index do |item, index| %> | |||
| <tr class=""> | |||
| <td><%= index + 1%></td> | |||
| <td> | |||
| <a target="_blank" href="<%= "/#{item&.project&.owner&.login}/#{item&.project&.identifier}"%>"> | |||
| <%= "#{item&.project&.owner&.real_name}/#{item&.project&.name}" %> | |||
| </a> | |||
| </td> | |||
| <td><%= item&.issues %></td> | |||
| <td><%= item&.closed_issues %></td> | |||
| <td><%= item&.project&.issues&.issue_issue.count %></td> | |||
| </tr> | |||
| <% end %> | |||
| </tbody> | |||
| </table> | |||
| @@ -7,11 +7,11 @@ | |||
| <%= form_tag(admins_projects_rank_index_path, method: :get, class: 'form-inline search-form flex-1', id: 'project-rank-date-form') do %> | |||
| <div class="input-group"> | |||
| <span class="input-group-text">开始日期</span> | |||
| <input class="form-control datetimepicker" type="text" name="begin_date" value="<%= params[:begin_date] || (Date.today - 7.days).to_s%>" aria-label="选择日期"> | |||
| <input class="form-control datetimepicker" type="text" name="begin_date" value="<%= params[:begin_date] || (Date.yesterday - 7.days).to_s%>" aria-label="选择日期"> | |||
| </div> | |||
| <div class="input-group"> | |||
| <span class="input-group-text">截止日期</span> | |||
| <input class="form-control datetimepicker" type="text" name="end_date" value="<%= params[:end_date] || Date.today.to_s%>" aria-label="选择日期"> | |||
| <input class="form-control datetimepicker" type="text" name="end_date" value="<%= params[:end_date] || Date.yesterday.to_s%>" aria-label="选择日期"> | |||
| </div> | |||
| <% end %> | |||
| <%= link_to '导出', "/项目活跃度排行.xls", class: 'btn btn-primary mr-3' %> | |||
| @@ -81,6 +81,7 @@ | |||
| <%= sidebar_item_group('#rank-submenu', '活跃度排行', icon: 'calendar') do %> | |||
| <li><%= sidebar_item(admins_users_rank_index_path, '用户活跃度排行', icon: 'user', controller: 'admins-users_rank') %></li> | |||
| <li><%= sidebar_item(admins_projects_rank_index_path, '项目活跃度排行', icon: 'database', controller: 'admins-projects_rank') %></li> | |||
| <li><%= sidebar_item(admins_issues_rank_index_path, '疑修活跃度排行', icon: 'calendar', controller: 'admins-issues_rank') %></li> | |||
| <% end %> | |||
| </li> | |||
| @@ -822,6 +822,7 @@ Rails.application.routes.draw do | |||
| resources :identity_verifications | |||
| resources :site_pages | |||
| resources :page_themes | |||
| resources :issues_rank, only: [:index] | |||
| resources :projects_rank, only: [:index] | |||
| resources :sites | |||
| resources :edu_settings | |||
| @@ -0,0 +1,5 @@ | |||
| class AddClosedIssuesToDailyProjectStatistics < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :daily_project_statistics, :closed_issues, :integer, default: 0 | |||
| end | |||
| end | |||