From 852f131e3b7e66ac9bbd093fa4af9362ecc7725a Mon Sep 17 00:00:00 2001
From: cxt <853663049@qq.com>
Date: Wed, 16 Oct 2019 10:40:49 +0800
Subject: [PATCH 1/3] =?UTF-8?q?=E7=AB=9E=E8=B5=9B=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E5=91=98=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../admins/competition_settings_controller.rb | 20 ++++++++++++
.../admins/competitions_controller.rb | 31 +++++++++++++++++++
app/models/competition.rb | 23 ++++++++++++++
.../admins/competition_settings/show.html.erb | 0
.../admins/competitions/enroll_list.html.erb | 0
app/views/admins/competitions/index.html.erb | 4 ++-
.../admins/competitions/online_switch.js.erb | 0
app/views/admins/competitions/publish.js.erb | 0
.../admins/competitions/shared/_list.html.erb | 30 ++++++++++++++++++
.../admins/competitions/shared/_td.html.erb | 27 ++++++++++++++++
.../admins/competitions/unpublish.js.erb | 0
config/routes.rb | 10 +++++-
12 files changed, 143 insertions(+), 2 deletions(-)
create mode 100644 app/controllers/admins/competition_settings_controller.rb
create mode 100644 app/views/admins/competition_settings/show.html.erb
create mode 100644 app/views/admins/competitions/enroll_list.html.erb
create mode 100644 app/views/admins/competitions/online_switch.js.erb
create mode 100644 app/views/admins/competitions/publish.js.erb
create mode 100644 app/views/admins/competitions/shared/_list.html.erb
create mode 100644 app/views/admins/competitions/shared/_td.html.erb
create mode 100644 app/views/admins/competitions/unpublish.js.erb
diff --git a/app/controllers/admins/competition_settings_controller.rb b/app/controllers/admins/competition_settings_controller.rb
new file mode 100644
index 000000000..390ad17e8
--- /dev/null
+++ b/app/controllers/admins/competition_settings_controller.rb
@@ -0,0 +1,20 @@
+class Admins::CompetitionSettingsController < Admins::BaseController
+ def show
+ @competition = current_competition
+ end
+
+ def update
+ Admins::SaveLaboratorySettingService.call(current_competition, form_params)
+ render_ok
+ end
+
+ private
+
+ def current_competition
+ @_current_competition ||= Competition.find(params[:competition_id])
+ end
+
+ def form_params
+ params.permit(:identifier, :name, :nav_logo, :login_logo, :tab_logo, :footer, navbar: %i[name link hidden])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/competitions_controller.rb b/app/controllers/admins/competitions_controller.rb
index 3d6bef819..3b9b63243 100644
--- a/app/controllers/admins/competitions_controller.rb
+++ b/app/controllers/admins/competitions_controller.rb
@@ -1,4 +1,6 @@
class Admins::CompetitionsController < Admins::BaseController
+ include CustomSortable
+ before_action :find_competition, except: [:index]
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
@@ -6,10 +8,39 @@ class Admins::CompetitionsController < Admins::BaseController
@competitions = custom_sort Competition.all, params[:sort_by], params[:sort_direction]
@params_page = params[:page] || 1
@competitions = paginate @competitions
+ ids = @competitions.map(&:id)
+ @member_count_map = TeamMember.where(competition_id: ids).group(:competition_id).count
respond_to do |format|
format.js
format.html
end
end
+
+ def publish
+ @competition.update_attributes!(:published_at, Time.now)
+ end
+
+ def unpublish
+ @competition.update_attributes!(:published_at, nil)
+ end
+
+ def online_switch
+ if @competition.status
+ @competition.update_attributes!(status: false)
+ else
+ @competition.update_attributes!(status: true, online_time: Time.now)
+ end
+ end
+
+ def enroll_list
+
+ end
+
+ private
+
+ def find_competition
+ @competition = Competition.find_by(id: params[:id])
+ end
+
end
\ No newline at end of file
diff --git a/app/models/competition.rb b/app/models/competition.rb
index 024478ad6..9055adefc 100644
--- a/app/models/competition.rb
+++ b/app/models/competition.rb
@@ -18,6 +18,29 @@ class Competition < ApplicationRecord
after_create :create_competition_modules
+ def mode_type
+ case mode
+ when 1
+ "课堂"
+ when 2
+ "实训"
+ when 3
+ "教学"
+ when 4
+ "托管"
+ else
+ "--"
+ end
+ end
+
+ def teacher_staff_num
+ teacher_staff ? "#{teacher_staff.minimum}~#{teacher_staff.maximum}" : "--"
+ end
+
+ def member_staff_num
+ member_staff ? "#{member_staff.minimum}~#{member_staff.maximum}" : "--"
+ end
+
# 是否上架
def published?
status?
diff --git a/app/views/admins/competition_settings/show.html.erb b/app/views/admins/competition_settings/show.html.erb
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/views/admins/competitions/enroll_list.html.erb b/app/views/admins/competitions/enroll_list.html.erb
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/views/admins/competitions/index.html.erb b/app/views/admins/competitions/index.html.erb
index 8fa238181..b97e26f94 100644
--- a/app/views/admins/competitions/index.html.erb
+++ b/app/views/admins/competitions/index.html.erb
@@ -3,5 +3,7 @@
<% end %>
- <%= render partial: 'admins/shixuns/shared/list', locals: { shixuns: @shixuns } %>
+ <%= render partial: 'admins/competitions/shared/list', locals: { competitions: @competitions } %>
+
+<%= render partial: 'admins/shared/modal/upload_file_modal', locals: { title: '上传图片' } %>
\ No newline at end of file
diff --git a/app/views/admins/competitions/online_switch.js.erb b/app/views/admins/competitions/online_switch.js.erb
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/views/admins/competitions/publish.js.erb b/app/views/admins/competitions/publish.js.erb
new file mode 100644
index 000000000..e69de29bb
diff --git a/app/views/admins/competitions/shared/_list.html.erb b/app/views/admins/competitions/shared/_list.html.erb
new file mode 100644
index 000000000..8f215d54c
--- /dev/null
+++ b/app/views/admins/competitions/shared/_list.html.erb
@@ -0,0 +1,30 @@
+
+
+ 序号 |
+ 竞赛主标题 |
+ 竞赛副标题 |
+ 模式 |
+ 报名人数 |
+ 指导老师 |
+ 参赛者 |
+ 主题图片796*397 |
+ 创建时间 |
+
+ 操作
+ |
+
+
+ <% if competitions.present? %>
+ <% competitions.each_with_index do |competition, index| %>
+
+ <% page_no = list_index_no(@params_page.to_i, index) %>
+ <%= render partial: "admins/competitions/shared/td",locals: {competition: competition, page_no: page_no} %>
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: competitions } %>
\ No newline at end of file
diff --git a/app/views/admins/competitions/shared/_td.html.erb b/app/views/admins/competitions/shared/_td.html.erb
new file mode 100644
index 000000000..d05974c86
--- /dev/null
+++ b/app/views/admins/competitions/shared/_td.html.erb
@@ -0,0 +1,27 @@
+<%= page_no %> |
+
+ <%= link_to competition.name, enroll_list_admins_competition_path(competition), :target => "_blank", :title => competition.name %>
+ |
+<%= competition.sub_title %> |
+<%= competition.mode_type %> |
+<%= @member_count_map&.fetch(competition.id, 0) || competition.team_members.count %> |
+<%= competition.teacher_staff_num %> |
+<%= competition.member_staff_num %> |
+
+ <% imageExists = File.exist?(disk_filename("Competition", competition.id)) %>
+ <% imageUrl = imageExists ? '/' + url_to_avatar(competition) + "?#{Time.now.to_i}" : '' %>
+ <%= image_tag(imageUrl, width: 60, height: 40, class: "preview-image competition-image-#{competition.id}", data: { toggle: 'tooltip', title: '点击预览' }, style: imageExists ? '' : 'display:none') %>
+ <%= javascript_void_link imageExists ? '重新上传' : '上传图片', class: 'action upload-competition-image-action', data: { source_id: competition.id, source_type: 'Competition', toggle: 'modal', target: '.admin-upload-file-modal' } %>
+ |
+<%= competition.created_at.strftime('%Y-%m-%d %H:%M') %> |
+
+ <%= link_to '配置', admins_competition_competition_setting_path(competition), class: 'action edit-action' %>
+
+ <% if !competition.status? && competition.published_at.blank? %>
+ <%= link_to '发布', publish_admins_competition_path(competition), class: 'action publish-action', method: :post, remote: true %>
+ <% else %>
+ <%= link_to '取消发布', unpublish_admins_competition_path(competition), class: 'action unpublish-action', method: :post, remote: true %>
+ <% end %>
+
+ <%= link_to competition.published? ? "下架" : "上架", online_switch_admins_competition_path(competition), class: 'action online-action', method: :post, remote: true %>
+ |
\ No newline at end of file
diff --git a/app/views/admins/competitions/unpublish.js.erb b/app/views/admins/competitions/unpublish.js.erb
new file mode 100644
index 000000000..e69de29bb
diff --git a/config/routes.rb b/config/routes.rb
index f6f8db066..605ae4194 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -981,7 +981,15 @@ Rails.application.routes.draw do
resource :laboratory_user, only: [:create, :destroy]
end
- resources :competitions, only: [:index, :destroy]
+ resources :competitions, only: [:index, :destroy] do
+ member do
+ post :publish
+ post :unpublish
+ post :online_switch
+ get :enroll_list
+ end
+ resource :competition_setting, only: [:show, :update]
+ end
end
resources :colleges, only: [] do
From 7125e71563179bfd416496f0fa99a1e851a5eeae Mon Sep 17 00:00:00 2001
From: p31729568
Date: Wed, 16 Oct 2019 10:53:37 +0800
Subject: [PATCH 2/3] weapp api
---
app/controllers/weapps/base_controller.rb | 34 ++++++++++
.../weapps/code_sessions_controller.rb | 24 +++++++
.../weapps/registers_controller.rb | 63 +++++++++++++++++++
app/controllers/weapps/sessions_controller.rb | 24 +++++++
app/controllers/weapps/verifies_controller.rb | 8 +++
app/libs/wechat/weapp.rb | 38 ++++++++++-
config/configuration.yml.example | 3 +
config/initializers/wechat_init.rb | 8 +++
config/routes.rb | 7 +++
9 files changed, 208 insertions(+), 1 deletion(-)
create mode 100644 app/controllers/weapps/base_controller.rb
create mode 100644 app/controllers/weapps/code_sessions_controller.rb
create mode 100644 app/controllers/weapps/registers_controller.rb
create mode 100644 app/controllers/weapps/sessions_controller.rb
create mode 100644 app/controllers/weapps/verifies_controller.rb
diff --git a/app/controllers/weapps/base_controller.rb b/app/controllers/weapps/base_controller.rb
new file mode 100644
index 000000000..fadf10fb6
--- /dev/null
+++ b/app/controllers/weapps/base_controller.rb
@@ -0,0 +1,34 @@
+class Weapps::BaseController < ApplicationController
+
+ private
+
+ def require_wechat_login!
+ return if session_unionid.present?
+
+ render_error('请先进行微信授权')
+ end
+
+ def weapp_session_key
+ Wechat::Weapp.session_key(session_openid)
+ end
+
+ def set_weapp_session_key(session_key)
+ Wechat::Weapp.write_session_key(session_openid, session_key)
+ end
+
+ def session_openid
+ session[:openid]
+ end
+
+ def set_session_openid(openid)
+ session[:openid] = openid
+ end
+
+ def session_unionid
+ session[:unionid]
+ end
+
+ def set_session_unionid(unionid)
+ session[:unionid] = unionid
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/weapps/code_sessions_controller.rb b/app/controllers/weapps/code_sessions_controller.rb
new file mode 100644
index 000000000..7c1978e5f
--- /dev/null
+++ b/app/controllers/weapps/code_sessions_controller.rb
@@ -0,0 +1,24 @@
+class Weapps::CodeSessionsController < Weapps::BaseController
+ def create
+ return render_error('code不能为空') if params[:code].blank?
+
+ result = Wechat::Weapp.jscode2session(params[:code])
+
+ set_session_openid(result['openid'])
+ set_weapp_session_key(result['session_key']) # weapp session_key写入缓存 后续解密需要
+
+ # 已授权,绑定过账号
+ open_user = OpenUser::Wechat.find_by(uid: result['unionid'])
+ if open_user.present? && open_user.user
+ set_session_unionid(result['unionid'])
+ successful_authentication(open_user.user)
+ else
+ # 新用户
+ user_info = Wechat::Weapp.decrypt(result['session_key'], params[:encrypted_data], params[:iv])
+
+ set_session_unionid(user_info['unionId'])
+ end
+
+ render_ok(openid: result['openid'])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/weapps/registers_controller.rb b/app/controllers/weapps/registers_controller.rb
new file mode 100644
index 000000000..0cbab7fd4
--- /dev/null
+++ b/app/controllers/weapps/registers_controller.rb
@@ -0,0 +1,63 @@
+class Weapps::RegistersController < Weapps::BaseController
+ before_action :require_wechat_login!
+
+ def create
+ # 查询验证码是否正确;type只可能是1或者8
+ type = phone_mail_type(params[:login].strip)
+ code = params[:code].strip
+
+ if type == 1
+ uid_logger("start register by phone: type is #{type}")
+ pre = 'p'
+ email = nil
+ phone = params[:login]
+ verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
+ else
+ uid_logger("start register by email: type is #{type}")
+ pre = 'm'
+ email = params[:login]
+ phone = nil
+ verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
+ end
+ uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
+ # check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
+ # todo 上线前请删除万能验证码"513231"
+ unless code == "513231" && request.subdomain == "test-newweb"
+ return render_error('验证码不正确') if verifi_code.try(:code) != code.strip
+ return render_error('验证码已失效') if !verifi_code&.effective?
+ end
+
+ login = User.generate_login(pre)
+ @user = User.new(admin: false, login: login, mail: email, phone: phone, type: 'User')
+ @user.password = params[:password]
+ # 现在因为是验证码,所以在注册的时候就可以激活
+ @user.activate
+ # 必须要用save操作,密码的保存是在users中
+ ActiveRecord::Base.transaction do
+ @user.save!
+ UserExtension.create!(user_id: @user.id)
+ # 绑定微信号
+ OpenUsers::Wechat.create!(user: @user, uid: session_unionid)
+
+ # 注册完成,手机号或邮箱想可以奖励500金币
+ RewardGradeService.call(
+ @user,
+ container_id: @user.id,
+ container_type: pre == 'p' ? 'Phone' : 'Mail',
+ score: 500
+ )
+ end
+ successful_authentication(@user)
+ session[:user_id] = @user.id
+
+ render_ok
+ end
+
+ private
+
+ # 1 手机类型;0 邮箱类型
+ # 注意新版的login是自动名生成的
+ def phone_mail_type value
+ value =~ /^1\d{10}$/ ? 1 : 0
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/weapps/sessions_controller.rb b/app/controllers/weapps/sessions_controller.rb
new file mode 100644
index 000000000..f65111399
--- /dev/null
+++ b/app/controllers/weapps/sessions_controller.rb
@@ -0,0 +1,24 @@
+class Weapps::SessionsController < Weapps::BaseController
+ before_action :require_wechat_login!
+
+ def create
+ return render_error('重复登录') if current_user.present? && current_user.logged?
+
+ user = User.try_to_login(params[:login], params[:password])
+
+ return render_error('错误的账号或密码') if user.blank?
+ return render_error('违反平台使用规范,账号已被锁定') if user.locked?
+ return render_error('错误的账号或密码') unless user.check_password?(params[:password].to_s)
+
+ if user.wechat_open_user && user.wechat_open_user.uid != session_unionid
+ render_error('该账号已被其它微信号绑定')
+ return
+ end
+
+ # 绑定微信号
+ OpenUsers::Wechat.create!(user: user, uid: session_unionid) if user.wechat_open_user.blank?
+
+ successful_authentication(user)
+ render_ok
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/weapps/verifies_controller.rb b/app/controllers/weapps/verifies_controller.rb
new file mode 100644
index 000000000..5d8f4056e
--- /dev/null
+++ b/app/controllers/weapps/verifies_controller.rb
@@ -0,0 +1,8 @@
+class Weapps::VerifiesController < Weapps::BaseController
+ before_action :require_wechat_login!
+
+ def create
+ valid = Wechat::Weapp.verify?(session_openid, params[:verify_string], params[:signature])
+ render_ok(valid: valid)
+ end
+end
\ No newline at end of file
diff --git a/app/libs/wechat/weapp.rb b/app/libs/wechat/weapp.rb
index 54f60fa2a..755c9351a 100644
--- a/app/libs/wechat/weapp.rb
+++ b/app/libs/wechat/weapp.rb
@@ -1,4 +1,4 @@
-class Wechat::App
+class Wechat::Weapp
class << self
attr_accessor :appid, :secret
@@ -7,5 +7,41 @@ class Wechat::App
def client
@_client ||= Wechat::Client.new(appid, secret)
end
+
+ def session_key(openid)
+ Rails.cache.read(session_key_cache_key(openid))
+ end
+
+ def write_session_key(openid, session_key)
+ Rails.cache.write(session_key_cache_key(openid), session_key)
+ end
+
+ def verify?(openid, str, signature)
+ session_key = session_key(openid)
+ Digest::SHA1.hexdigest("#{str}#{session_key}") == signature
+ end
+
+ def decrypt(session_key, encrypted_data, iv)
+ session_key = Base64.decode64(session_key)
+ encrypted_data = Base64.decode64(encrypted_data)
+ iv = Base64.decode64(iv)
+
+ cipher = OpenSSL::Cipher::AES.new(128, :CBC)
+ cipher.decrypt
+ cipher.padding = 0
+ cipher.key = session_key
+ cipher.iv = iv
+ data = cipher.update(encrypted_data) << cipher.final
+ result = JSON.parse(data[0...-data.last.ord])
+
+ raise Wechat::Error, '解密错误' if result.dig('watermark', 'appid') != appid
+ result
+ end
+
+ private
+
+ def session_key_cache_key(openid)
+ "weapp:#{appid}:#{openid}:session_key"
+ end
end
end
\ No newline at end of file
diff --git a/config/configuration.yml.example b/config/configuration.yml.example
index 612011a7f..6ead04a54 100644
--- a/config/configuration.yml.example
+++ b/config/configuration.yml.example
@@ -18,6 +18,9 @@ defaults: &defaults
wechat:
appid: 'test'
secret: 'test'
+ weapp:
+ appid: 'test'
+ secret: 'test'
development:
<<: *defaults
diff --git a/config/initializers/wechat_init.rb b/config/initializers/wechat_init.rb
index 946e5f638..3fd8f9485 100644
--- a/config/initializers/wechat_init.rb
+++ b/config/initializers/wechat_init.rb
@@ -1,9 +1,12 @@
wechat_config = {}
+weapp_config = {}
begin
config = Rails.application.config_for(:configuration)
wechat_config = config['wechat']
+ weapp_config = config['weapp']
raise 'wechat config missing' if wechat_config.blank?
+ raise 'weapp config missing' if weapp_config.blank?
rescue => ex
raise ex if Rails.env.production?
@@ -12,5 +15,10 @@ rescue => ex
wechat_config = {}
end
+# 网站应用
Wechat::OfficialAccount.appid = wechat_config['appid']
Wechat::OfficialAccount.secret = wechat_config['secret']
+
+# 小程序
+Wechat::Weapp.appid = weapp_config['appid']
+Wechat::Weapp.secret = weapp_config['secret']
diff --git a/config/routes.rb b/config/routes.rb
index 605ae4194..1ef62c0e6 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -829,6 +829,13 @@ Rails.application.routes.draw do
get '/auth/qq/callback', to: 'oauth/qq#create'
get '/auth/wechat/callback', to: 'oauth/wechat#create'
resource :bind_user, only: [:create]
+
+ namespace :weapps do
+ resource :session, only: [:create]
+ resource :register, only: [:create]
+ resource :code_session, only: [:create]
+ resource :verify, only: [:create]
+ end
end
namespace :admins do
From e7723a600318836bb3c28458ce2397fb98480974 Mon Sep 17 00:00:00 2001
From: p31729568
Date: Wed, 16 Oct 2019 11:32:54 +0800
Subject: [PATCH 3/3] weapp: home api
---
app/controllers/weapps/homes_controller.rb | 12 ++++++++++++
app/views/weapps/homes/show.json.jbuilder | 14 ++++++++++++++
config/routes.rb | 1 +
3 files changed, 27 insertions(+)
create mode 100644 app/controllers/weapps/homes_controller.rb
create mode 100644 app/views/weapps/homes/show.json.jbuilder
diff --git a/app/controllers/weapps/homes_controller.rb b/app/controllers/weapps/homes_controller.rb
new file mode 100644
index 000000000..efb80b898
--- /dev/null
+++ b/app/controllers/weapps/homes_controller.rb
@@ -0,0 +1,12 @@
+class Weapps::HomesController < Weapps::BaseController
+ def show
+ # banner图
+ @images = PortalImage.where(status: true).order(position: :asc)
+
+ # 热门实训
+ @shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(4)
+
+ # 热门实践课程
+ @subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(4)
+ end
+end
\ No newline at end of file
diff --git a/app/views/weapps/homes/show.json.jbuilder b/app/views/weapps/homes/show.json.jbuilder
new file mode 100644
index 000000000..d2a451030
--- /dev/null
+++ b/app/views/weapps/homes/show.json.jbuilder
@@ -0,0 +1,14 @@
+json.images do
+ json.array! @images do |image|
+ json.path image.link
+ json.image_url Util::FileManage.source_disk_file_url(image)
+ end
+end
+
+json.shixuns do
+ json.partial! 'shixuns/shixun', locals: { shixuns: @shixuns }
+end
+
+json.subjects do
+ json.partial! 'subjects/subject', locals: { subjects: @subjects }
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 1ef62c0e6..4445278de 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -831,6 +831,7 @@ Rails.application.routes.draw do
resource :bind_user, only: [:create]
namespace :weapps do
+ resource :home, only: [:show]
resource :session, only: [:create]
resource :register, only: [:create]
resource :code_session, only: [:create]