| @@ -111,7 +111,9 @@ class AccountsController < ApplicationController | |||
| sync_params = { | |||
| password: params[:password].to_s, | |||
| email: @user.mail | |||
| email: @user.mail, | |||
| login_name: @user.login, | |||
| source_id: 0 | |||
| } | |||
| interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params) | |||
| @@ -8,6 +8,9 @@ class Admins::NpsController < Admins::BaseController | |||
| @user_nps = @user_nps.where(sql, keyword: "%#{keyword}%") | |||
| end | |||
| @user_nps = @user_nps.where("action_type != 'close'") if params[:done_score].present? | |||
| @min_score = @user_nps.where("action_type != 'close'").minimum("score") | |||
| @max_score = @user_nps.where("action_type != 'close'").maximum("score") | |||
| @score_total_count = UserNp.where("action_type !='close'").count | |||
| @user_nps = paginate @user_nps.includes(:user) | |||
| end | |||
| @@ -22,6 +22,8 @@ class CommitLogsController < ApplicationController | |||
| CommitLog.create(user: user, project: project, repository_id: repository_id, | |||
| name: repository_name, full_name: repository_full_name, | |||
| ref: ref, commit_id: commit_id, message: message) | |||
| # 统计数据新增 | |||
| CacheAsyncSetJob.perform_later("project_common_service", {commits: 1}, project.id) | |||
| end | |||
| end | |||
| @@ -31,6 +31,7 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||
| Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate! | |||
| @organization = Organizations::CreateService.call(current_user, organization_params) | |||
| Util.write_file(@image, avatar_path(@organization)) if params[:image].present? | |||
| Cache::V2::OwnerCommonService.new(@organization.id).reset | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -48,6 +49,7 @@ class Organizations::OrganizationsController < Organizations::BaseController | |||
| Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload) | |||
| Util.write_file(@image, avatar_path(@organization)) if params[:image].present? | |||
| Cache::V2::OwnerCommonService.new(@organization.id).reset | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -81,15 +81,15 @@ class Organization < Owner | |||
| scope :with_visibility, ->(visibility) { joins(:organization_extension).where(organization_extensions: {visibility: visibility}) if visibility.present? } | |||
| after_save :reset_cache_data | |||
| # after_save :reset_cache_data | |||
| def gitea_token | |||
| team_users.joins(:team).where(teams: {authorize: "owner"}).take&.user&.gitea_token | |||
| end | |||
| def reset_cache_data | |||
| Cache::V2::OwnerCommonService.new(self.id).reset | |||
| end | |||
| # def reset_cache_data | |||
| # Cache::V2::OwnerCommonService.new(self.id).reset | |||
| # end | |||
| def self.build(name, nickname, gitea_token=nil) | |||
| self.create!(login: name, nickname: nickname, gitea_token: gitea_token) | |||
| @@ -30,6 +30,15 @@ class Admins::UserQuery < ApplicationQuery | |||
| users = users.joins(user_extension: :school).where(schools: { auto_users_trial: params[:auto_trial].to_i == 1 }) | |||
| end | |||
| # 第三方账户类型 | |||
| if params[:open_user_type].present? | |||
| if params[:open_user_type] == "Forge" | |||
| users = users.left_joins(:open_users).where(open_users: {id: nil}) | |||
| else | |||
| users = users.joins(:open_users).where(open_users: {type: params[:open_user_type]}) | |||
| end | |||
| end | |||
| # 关键字检索 | |||
| keyword = params[:keyword].to_s.strip.presence | |||
| if keyword | |||
| @@ -1,5 +1,5 @@ | |||
| class Cache::V2::ProjectCommonService < ApplicationService | |||
| attr_reader :project_id, :owner_id, :name, :identifier, :description, :visits, :watchers, :praises, :forks, :issues, :pullrequests | |||
| attr_reader :project_id, :owner_id, :name, :identifier, :description, :visits, :watchers, :praises, :forks, :issues, :pullrequests, :commits | |||
| attr_accessor :project | |||
| def initialize(project_id, params={}) | |||
| @@ -14,6 +14,7 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @pullrequests = params[:pullrequests] | |||
| @commits = params[:commits] | |||
| end | |||
| def read | |||
| @@ -81,6 +82,10 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| "pullrequests" | |||
| end | |||
| def commits_key | |||
| "commits" | |||
| end | |||
| def project_common | |||
| result = $redis_cache.hgetall(project_common_key) | |||
| result.blank? ? reset_project_common : result | |||
| @@ -149,6 +154,11 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| Cache::V2::ProjectRankService.call(@project_id, {pullrequests: @pullrequests}) | |||
| Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {pullrequests: @pullrequests}) | |||
| end | |||
| if @commits.present? | |||
| $redis_cache.hincrby(project_common_key, commits_key, @commits) | |||
| Cache::V2::ProjectRankService.call(@project_id, {commits: @commits}) | |||
| Cache::V2::ProjectDateRankService.call(@project_id, Date.today, {commits: @commits}) | |||
| end | |||
| end | |||
| $redis_cache.hgetall(project_common_key) | |||
| @@ -194,6 +204,10 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| $redis_cache.hset(project_common_key, pullrequests_key, PullRequest.where(project_id: @project_id).count) | |||
| end | |||
| def reset_project_commits | |||
| $redis_cache.hset(project_common_key, commits_key, CommitLog.where(project_id: @project_id).count) | |||
| end | |||
| def reset_project_common | |||
| load_project | |||
| return unless @project.present? | |||
| @@ -209,6 +223,7 @@ class Cache::V2::ProjectCommonService < ApplicationService | |||
| reset_project_forks | |||
| reset_project_issues | |||
| reset_project_pullrequests | |||
| reset_project_commits | |||
| $redis_cache.hgetall(project_common_key) | |||
| end | |||
| @@ -1,5 +1,6 @@ | |||
| # 项目日活跃度计算存储 | |||
| class Cache::V2::ProjectDateRankService < ApplicationService | |||
| attr_reader :project_id, :rank_date, :visits, :praises, :forks, :issues, :pullrequests | |||
| attr_reader :project_id, :rank_date, :visits, :praises, :forks, :issues, :pullrequests, :commits | |||
| attr_accessor :project_common | |||
| def initialize(project_id, rank_date=Date.today, params={}) | |||
| @@ -10,6 +11,7 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @pullrequests = params[:pullrequests] | |||
| @commits = params[:commits] | |||
| end | |||
| def read | |||
| @@ -37,7 +39,7 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| $redis_cache.zincrby(project_rank_key, @praises.to_i * 5, @project_id) | |||
| end | |||
| if @forks.present? | |||
| $redis_cache.zincrby(project_rank_key, @forks.to_i * 5, @project_id) | |||
| $redis_cache.zincrby(project_rank_key, @forks.to_i * 10, @project_id) | |||
| end | |||
| if @issues.present? | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 10, @project_id) | |||
| @@ -45,6 +47,9 @@ class Cache::V2::ProjectDateRankService < ApplicationService | |||
| if @pullrequests.present? | |||
| $redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id) | |||
| end | |||
| if @commits.present? | |||
| $redis_cache.zincrby(project_rank_key, @commits.to_i * 1, @project_id) | |||
| end | |||
| $redis_cache.zscore(project_rank_key, @project_id) | |||
| end | |||
| @@ -1,5 +1,5 @@ | |||
| class Cache::V2::ProjectRankService < ApplicationService | |||
| attr_reader :project_id, :visits, :praises, :forks, :issues, :pullrequests | |||
| attr_reader :project_id, :visits, :praises, :forks, :issues, :pullrequests, :commits | |||
| attr_accessor :project_common | |||
| def initialize(project_id, params={}) | |||
| @@ -9,6 +9,7 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| @forks = params[:forks] | |||
| @issues = params[:issues] | |||
| @pullrequests = params[:pullrequests] | |||
| @commits = params[:commits] | |||
| end | |||
| def read | |||
| @@ -54,7 +55,7 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| $redis_cache.zincrby(project_rank_key, @praises.to_i * 5, @project_id) | |||
| end | |||
| if @forks.present? | |||
| $redis_cache.zincrby(project_rank_key, @forks.to_i * 5, @project_id) | |||
| $redis_cache.zincrby(project_rank_key, @forks.to_i * 10, @project_id) | |||
| end | |||
| if @issues.present? | |||
| $redis_cache.zincrby(project_rank_key, @issues.to_i * 10, @project_id) | |||
| @@ -62,6 +63,9 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| if @pullrequests.present? | |||
| $redis_cache.zincrby(project_rank_key, @pullrequests.to_i * 10, @project_id) | |||
| end | |||
| if @commits.present? | |||
| $redis_cache.zincrby(project_rank_key, @commits.to_i * 1, @project_id) | |||
| end | |||
| reset_user_project_rank | |||
| end | |||
| @@ -70,7 +74,7 @@ class Cache::V2::ProjectRankService < ApplicationService | |||
| def reset_project_rank | |||
| load_project_common | |||
| score = @project_common["visits"].to_i * 1 + @project_common["praises"].to_i * 5 + @project_common["forks"].to_i * 5 + @project_common["issues"].to_i * 10 + @project_common["pullrequests"].to_i * 10 | |||
| score = @project_common["visits"].to_i * 1 + @project_common["praises"].to_i * 5 + @project_common["forks"].to_i * 10 + @project_common["issues"].to_i * 10 + @project_common["pullrequests"].to_i * 10 + @project_common["commits"].to_i * 1 | |||
| $redis_cache.zadd(project_rank_key, score, @project_id) | |||
| reset_user_project_rank | |||
| @@ -13,12 +13,31 @@ | |||
| <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> | |||
| <span style="margin-left: 50px;margin-right: 10px;">NPS系统开关</span> | |||
| <input type="checkbox" <% if @on_off_switch %>checked<%end %> data-toggle="toggle" data-onstyle="primary" id="nps_toggle" data-on="开" data-off="关" data-size="small"> | |||
| <input type="checkbox" | |||
| <% if @on_off_switch %>checked | |||
| <% end %> data-toggle="toggle" data-onstyle="primary" id="nps_toggle" data-on="开" data-off="关" data-size="small"> | |||
| <% end %> | |||
| </div> | |||
| <div class="box py-0 pt-4 pl-4 daily-school-statistic-title" > | |||
| <p style="font-weight: bold">数据统计:</p> | |||
| <p> | |||
| 评分用户数/用户总数:<span class="text-danger"><%= @score_total_count %>/<%= UserNp.count %></span>, | |||
| 平均评分:<span class="text-danger"><%= UserNp.where("action_type !='close'").average(:score).to_f.round(1) %></span>, | |||
| <% @user_nps_mid = @score_total_count % 2 == 0 ? @score_total_count / 2 : (@score_total_count + 1) / 2 %> | |||
| 评分中位数:<span class="text-danger"><%= UserNp.where("action_type !='close'").order("score").pluck(:score)[@user_nps_mid - 1].to_i %></span>, | |||
| 最低评分/评分人数:<span class="text-danger"><%=@min_score.to_i %>/<%= UserNp.where("action_type !='close'").where(score: @min_score).count %></span>, | |||
| 最高评分/评分人数:<span class="text-danger"><%=@max_score.to_i %>/<%= UserNp.where("action_type !='close'").where(score: @max_score).count %></span> | |||
| </p> | |||
| <p style="padding-bottom: 10px !important;"> | |||
| 填写意见用户数/用户总数:<span class="text-danger"><%= UserNp.where("memo is not null").count %>/<%= UserNp.count %></span>, | |||
| 期待更加丰富的功能:<span class="text-danger"><%= UserNp.where("memo like '%期待更加丰富的功能%'").count %></span>, | |||
| 希望有新手引导:<span class="text-danger"><%= UserNp.where("memo like '%希望有新手引导%'").count %></span>, | |||
| 提升用户体验:<span class="text-danger"><%= UserNp.where("memo like '%用户体验需进一步提升%'").count %></span>, | |||
| 其他:<span class="text-danger"><%= UserNp.where("memo is not null").where.not(id: UserNp.where("memo like '%期待更加丰富的功能%' or memo like '%希望有新手引导%' or memo like '%用户体验需进一步提升%' ").ids).count %></span> | |||
| </p> | |||
| </div> | |||
| <div class="box admin-list-container users-list-container"> | |||
| <%= render partial: 'admins/nps/user_np_list', locals: { user_nps: @user_nps } %> | |||
| </div> | |||
| @@ -15,7 +15,11 @@ | |||
| <% identity_options = [['全部', ''], ['教师', 0], ['学生', 1], ['专业人士', 2]] %> | |||
| <%= select_tag(:identity, options_for_select(identity_options), class: 'form-control') %> | |||
| </div> | |||
| <div class="form-group mr-2"> | |||
| <label for="identity">类型:</label> | |||
| <% open_user_type_options = [['所有用户', ''], ['头歌同步', "OpenUsers::Educoder"], ['平台注册', "Forge"],] %> | |||
| <%= select_tag(:open_user_type, options_for_select(open_user_type_options), class: 'form-control') %> | |||
| </div> | |||
| <%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: 'ID/姓名/邮箱/手机号检索') %> | |||