parent
4ff44c382e
commit
ed125af92d
@ -0,0 +1,14 @@
|
|||||||
|
class Admins::ImportCompetitionScoresController < Admins::BaseController
|
||||||
|
def create
|
||||||
|
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||||
|
|
||||||
|
result = Admins::ImportCompetitionScoreService.call(params[:file].to_io, current_competition)
|
||||||
|
render_ok(result)
|
||||||
|
rescue Admins::ImportCompetitionScoreService::Error => ex
|
||||||
|
render_error(ex)
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_competition
|
||||||
|
competition = Competition.find_by!(id: params[:competition_id])
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,20 @@
|
|||||||
|
class Admins::ImportCompetitionScoreExcel < BaseImportXlsx
|
||||||
|
Data = Struct.new(:competition_team_id, :score)
|
||||||
|
|
||||||
|
def read_each(&block)
|
||||||
|
sheet.each_row_streaming(pad_cells: true, offset: 1) do |row|
|
||||||
|
data = row.map(&method(:cell_value))[0..1]
|
||||||
|
block.call Data.new(*data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def check_sheet_valid!
|
||||||
|
raise_import_error('请按照模板格式导入') if sheet.row(1).size != 2
|
||||||
|
end
|
||||||
|
|
||||||
|
def cell_value(obj)
|
||||||
|
obj&.cell_value&.to_s&.strip
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,59 @@
|
|||||||
|
class Admins::ImportCompetitionScoreService < ApplicationService
|
||||||
|
Error = Class.new(StandardError)
|
||||||
|
|
||||||
|
attr_reader :file, :competition, :result
|
||||||
|
|
||||||
|
def initialize(file, competition)
|
||||||
|
@file = file
|
||||||
|
@competition = competition
|
||||||
|
@result = { success: 0, fail: [] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
raise Error, '文件不存在' if file.blank?
|
||||||
|
|
||||||
|
# 创建所有战队的得分记录
|
||||||
|
create_all_records
|
||||||
|
|
||||||
|
excel = Admins::ImportCompetitionScoreExcel.new(file)
|
||||||
|
excel.read_each(&method(:update_competition_score)) # 更新单个战队成绩
|
||||||
|
|
||||||
|
result
|
||||||
|
rescue ApplicationImport::Error => ex
|
||||||
|
raise Error, ex.message
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def update_competition_score(data)
|
||||||
|
team = competition.competition_scores.find_by(competition_team_id: data.competition_team_id)
|
||||||
|
raise "id为#{data.id}的战队不存在" if team.blank?
|
||||||
|
team.update!(score: data.score)
|
||||||
|
|
||||||
|
result[:success] += 1
|
||||||
|
rescue Exception => ex
|
||||||
|
fail_data = data.as_json
|
||||||
|
fail_data[:data] = fail_data.values.join(',')
|
||||||
|
fail_data[:message] = ex.message
|
||||||
|
|
||||||
|
result[:fail] << fail_data
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_all_records
|
||||||
|
competition.competition_scores.destroy_all
|
||||||
|
|
||||||
|
stage = competition.competition_stages.first
|
||||||
|
|
||||||
|
attrs = %i[
|
||||||
|
competition_id competition_stage_id score cost_time user_id competition_team_id created_at updated_at
|
||||||
|
]
|
||||||
|
|
||||||
|
CompetitionScore.bulk_insert(*attrs) do |worker|
|
||||||
|
base_attr = { competition_id: competition.id, competition_stage_id: stage&.id.to_i,
|
||||||
|
score: 0, cost_time: 0 }
|
||||||
|
competition.competition_teams.each do |team|
|
||||||
|
worker.add(base_attr.merge(user_id: team.user_id).merge(competition_team_id: team.id))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,32 @@
|
|||||||
|
<div class="modal fade admin-import-competition-score-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">导入成绩</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="admin-import-competition-score-form" enctype="multipart/form-data">
|
||||||
|
<%= hidden_field_tag(:competition_id, nil) %>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">文件</span>
|
||||||
|
</div>
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" name="file" class="upload-file-input" id="import-competition-score-input" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
|
||||||
|
<label class="custom-file-label file-names" for="import-user-input">选择文件</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="error text-danger"></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
|
||||||
|
<button type="button" class="btn btn-primary submit-btn">确认</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in new issue