diff --git a/app/controllers/admins/import_users_controller.rb b/app/controllers/admins/import_users_controller.rb index 5d8a60ce6..4575b08d5 100644 --- a/app/controllers/admins/import_users_controller.rb +++ b/app/controllers/admins/import_users_controller.rb @@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController def create return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile) - result = Admins::ImportUserService.call(params[:file].to_io) + result = Admins::ImportUserFromExcelService.call(params[:file].to_io) render_ok(result) rescue Admins::ImportUserService::Error => ex render_error(ex) diff --git a/app/imports/admins/new_import_user_from_excel.rb b/app/imports/admins/new_import_user_from_excel.rb new file mode 100644 index 000000000..b9a452cf1 --- /dev/null +++ b/app/imports/admins/new_import_user_from_excel.rb @@ -0,0 +1,15 @@ +class Admins::NewImportUserFromExcel < BaseImportXlsx + UserData = Struct.new(:login, :email, :password, :nickname) + + def read_each(&block) + sheet.each_row_streaming(pad_cells: true, offset: 1) do |row| + data = row.map(&method(:cell_value))[0..3] + block.call UserData.new(*data) + end + end + + private + def cell_value(obj) + obj&.cell_value + end +end \ No newline at end of file diff --git a/app/services/admins/import_user_from_excel_service.rb b/app/services/admins/import_user_from_excel_service.rb new file mode 100644 index 000000000..709551c23 --- /dev/null +++ b/app/services/admins/import_user_from_excel_service.rb @@ -0,0 +1,71 @@ +class Admins::ImportUserFromExcelService < ApplicationService + Error = Class.new(StandardError) + + attr_reader :file, :result + + def initialize(file) + @file = file + @result = { success: 0, fail: [] } + end + + def call + raise Error, '文件不存在' if file.blank? + excel = Admins::NewImportUserFromExcel.new(file) + + excel.read_each(&method(:save_user)) + result + rescue ApplicationImport::Error => ex + raise Error, ex.message + end + + private + def save_user(data) + user = find_user(data) + if user.blank? + create_user(data) + result[:success] +=1 + else + fail_data = data.as_json + fail_data[:data] = fail_data.values.join(",") + fail_data[:message] = '用户已存在' + result[:fail] << fail_data + end + + 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_user(data) + ActiveRecord::Base.transaction do + username = data.login&.gsub(/\s+/, "") + email = data.email&.gsub(/\s+/, "") + password = data.password + nickname = data.nickname&.gsub(/\s+/, "") + raise Error, "无法使用以下关键词:#{username},请重新命名" if ReversedKeyword.check_exists?(data.login) + Register::RemoteForm.new({username: username, email: email, password: password, platform: 'forge'}).validate! + user = User.new(admin: false, login: username, mail: email, nickname: nickname, platform: 'forge' , type: "User") + user.password = password + user.activate + raise Error, user.errors.full_messages.join(",") unless user.valid? + interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password}) + if interactor.success? + gitea_user = interactor.result + result = Gitea::User::GenerateTokenService.call(username, password) + user.gitea_token = result['sha1'] + user.gitea_uid = gitea_user[:body]['id'] + UserExtension.create!(user_id: user.id) if user.save! + else + raise interactor.error, 'gitea user create error' + end + + user + end + end + + def find_user(data) + User.find_by(login: data.login) + end +end \ No newline at end of file diff --git a/app/views/admins/users/index.html.erb b/app/views/admins/users/index.html.erb index e21a3d665..2f41ffdb6 100644 --- a/app/views/admins/users/index.html.erb +++ b/app/views/admins/users/index.html.erb @@ -31,7 +31,9 @@ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %> <% end %> - <%= javascript_void_link '导入用户', class: 'btn btn-secondary btn-sm', data: { toggle: 'modal', target: '.admin-import-user-modal'} %> + <%= link_to '下载导入模板', "/导入用户模板.xlsx", class: 'btn btn-secondary mr-3' %> + + <%= javascript_void_link '导入用户', class: 'btn btn-secondary', data: { toggle: 'modal', target: '.admin-import-user-modal'} %> diff --git a/public/导入用户模板.xlsx b/public/导入用户模板.xlsx new file mode 100644 index 000000000..c538bed63 Binary files /dev/null and b/public/导入用户模板.xlsx differ