diff --git a/Gemfile b/Gemfile index 6cf60e0e..d89f9a24 100644 --- a/Gemfile +++ b/Gemfile @@ -67,6 +67,9 @@ gem 'oauth2' gem 'axlsx', '3.0.0.pre' gem 'axlsx_rails', '0.3.0' +# state machine +gem 'aasm' + #Ruby 2.2+ has removed test/unit from the core library. if RUBY_VERSION>='2.2' gem 'test-unit', '~> 3.0' diff --git a/app/controllers/libraries_controller.rb b/app/controllers/libraries_controller.rb new file mode 100644 index 00000000..ce34e603 --- /dev/null +++ b/app/controllers/libraries_controller.rb @@ -0,0 +1,61 @@ +class LibrariesController < ApplicationController + before_filter :require_login + + def index + libraries = Library.where(nil) + + libraries = + if params[:filter] == 'mine' + libraries.where(user_id: current_user.id).order('created_at desc') + else + libraries.where(status: :published).order('visited_count desc') + end + + search = params[:search].to_s.strip + libraries = libraries.where('title LIKE ?', "%#{search}%") if search.present? + + @libraries = paginateHelper libraries.includes(user: :user_extensions) + end + + def show + @library = Library.find(params[:id]) + @library.increment_visited_count! + end + + def new + @library = current_user.libraries.new + end + + def create + @library = current_user.libraries.new + Libraries::SaveService.new(@library, current_user, params).call + redirect_to library_path(id: @library.id) + rescue ActiveRecord::RecordInvalid => _ + render 'new' + end + + def edit + @library = current_library + end + + def update + @library = current_library + Libraries::SaveService.new(@library, current_user, params).call + redirect_to library_path(id: @library.id) + rescue ActiveRecord::RecordInvalid => _ + render 'edit' + end + + def publish + Libraries::SubmitService.new(current_library).call + render json: { status: 0 } + rescue Libraries::SubmitService::Error => ex + render json: { status: 0, message: ex.message } + end + + private + + def current_library + @_current_library ||= current_user.libraries.find(params[:id]) + end +end \ No newline at end of file diff --git a/app/controllers/managements/library_applies_controller.rb b/app/controllers/managements/library_applies_controller.rb new file mode 100644 index 00000000..512f47b4 --- /dev/null +++ b/app/controllers/managements/library_applies_controller.rb @@ -0,0 +1,47 @@ +class Managements::LibraryAppliesController < Managements::BaseController + before_filter :set_menu_type + + def index + applies = LibraryApply.order('library_applies.updated_at desc') + + search = params[:search].to_s.strip + if search.present? + applies = applies.joins(:library) + .where('libraries.uuid like :search or libraries.title like :search', search: "%#{search}%") + end + + applies = applies.where(status: params[:status].presence || :pending) + + @library_applies = paginateHelper applies.includes(library: { user: :user_extensions }) + + respond_to do |format| + format.js + format.html + end + end + + def agree + Libraries::AgreeApplyService.new(current_library_apply, current_user).call + render json: { status: 0 } + rescue Libraries::AgreeApplyService::Error => e + render json: { status: -1, message: e.message } + end + + def refuse + Libraries::RefuseApplyService.new(current_library_apply, current_user, reason: params[:reason]).call + render json: { status: 0 } + rescue Libraries::RefuseApplyService::Error => e + render json: { status: -1, message: e.message } + end + + private + + def current_library_apply + @_current_library_apply ||= LibraryApply.find(params[:id]) + end + + def set_menu_type + @menu_type = 10 + @sub_type = 8 + end +end \ No newline at end of file diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 34fa1a8d..83d80b3e 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -727,16 +727,17 @@ module ApplicationHelper when 9 sub_type == 1 ? "实训留言列表" : "" when 10 - sub_type == 1 ? "实名认证" : - (sub_type == 2 ? "试用授权" : - (sub_type == 3 ? "部门审批" : - (sub_type == 4 ? "单位审批" : - (sub_type == 5 ? "实训发布" : - (sub_type == 6 ? "实训课程发布" : "职业认证") - ) - ) - ) - ) + case sub_type + when 1 then '实名认证' + when 2 then '试用授权' + when 3 then '部门审批' + when 4 then '单位审批' + when 5 then '实训发布' + when 6 then '实训课程发布' + when 7 then '职业认证' + when 8 then '文库发布' + else '职业认证' + end when 11 "工程认证+" when 12 @@ -7430,6 +7431,8 @@ def tiding_url tiding project_pull_requests_path(tiding.parent_container_id) when 'Department' my_account_path + when 'Library' + tiding.tiding_type == 'System' ? library_applies_path : library_path(tiding.container_id) end end diff --git a/app/libs/util.rb b/app/libs/util.rb new file mode 100644 index 00000000..e72029ae --- /dev/null +++ b/app/libs/util.rb @@ -0,0 +1,7 @@ +module Util + module_function + + def generate_time_uuid + "#{Time.zone.now.strftime('%Y%m%d%H%M%S')}#{Random.rand(10**8).to_i}" + end +end \ No newline at end of file diff --git a/app/models/library.rb b/app/models/library.rb new file mode 100644 index 00000000..735445c9 --- /dev/null +++ b/app/models/library.rb @@ -0,0 +1,46 @@ +class Library < ActiveRecord::Base + include AASM + + belongs_to :user + + has_many :library_applies, dependent: :delete_all + has_many :attachments, as: :container + + attr_accessible :title, :content + + validates :title, presence: true + validates :content, presence: true + validates :uuid, presence: true, uniqueness: true + + aasm(:status) do + state :pending, initiali: true + state :processing + state :refused + state :published + + event :submit do + transitions from: [:pending, :refused], to: :processing + end + + event :refuse do + transitions from: :processing, to: :refused + end + + event :publish do + transitions from: :processing, to: :published + end + end + + def generate_uuid + uuid = Util.generate_time_uuid + while Library.exists?(uuid: uuid) + uuid = Util.generate_time_uuid + end + + self.uuid = uuid + end + + def increment_visited_count! + Library.connection.execute("update libraries set visited_count = COALESCE(visited_count, 0) + 1 where id = #{id}") + end +end \ No newline at end of file diff --git a/app/models/library_apply.rb b/app/models/library_apply.rb new file mode 100644 index 00000000..9c1e183a --- /dev/null +++ b/app/models/library_apply.rb @@ -0,0 +1,19 @@ +class LibraryApply < ActiveRecord::Base + include AASM + + belongs_to :library + + aasm(:status) do + state :pending, initiali: true + state :refused + state :agreed + + event :refuse do + transitions from: :pending, to: :refused + end + + event :agree do + transitions from: :pending, to: :agreed + end + end +end \ No newline at end of file diff --git a/app/models/tiding.rb b/app/models/tiding.rb index ec8c68d8..6b40615c 100644 --- a/app/models/tiding.rb +++ b/app/models/tiding.rb @@ -358,6 +358,14 @@ class Tiding < ActiveRecord::Base " " when 'Department' "你选填的二级单位:#{self.container.try(:name)}(#{self.container.try(:school).name})因不符合规范,已被系统删除.请重新选择" + when 'Library' + library = Library.find_by(id: container_id) + if tiding_type == 'Apply' + "申请发布文库:#{library.try(:name)}" + elsif tiding_type == 'System' + text = status == 1 ? "审核已通过" : "审核未通过,
原因:#{extra}" + "你提交的发布文库申请:#{library.try(:name)},#{text}" + end else logger.error "error type: 1" end diff --git a/app/models/user.rb b/app/models/user.rb index db1ff58a..c206d51e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -250,6 +250,7 @@ class User < Principal has_many :ec_course_users + has_many :libraries, dependent: :destroy ##### scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") } diff --git a/app/services/libraries/agree_apply_service.rb b/app/services/libraries/agree_apply_service.rb new file mode 100644 index 00000000..8d901b67 --- /dev/null +++ b/app/services/libraries/agree_apply_service.rb @@ -0,0 +1,32 @@ +class Libraries::AgreeApplyService + Error = Class.new(StandardError) + + attr_reader :library_apply, :library, :user + + def initialize(library_apply, user) + @library_apply = library_apply + @library = library_apply.library + @user = user + end + + def call + raise Error, '该状态下不能进行此操作' unless library_apply.may_agree? + + ActiveRecord::Base.transaction do + library_apply.agree! + library_apply.library.publish! + + # 将消息改为已处理 + Tiding.where(container_id: library.id, container_type: 'Library', tiding_type: 'Apply', status: 0).update_all(status: 1) + notify_library_author! + end + end + + private + + def notify_library_author! + Tiding.create!(user_id: library.user_id, trigger_user_id: 1, + container_id: library.id, container_type: 'Library', + tiding_type: 'System', status: 1) + end +end \ No newline at end of file diff --git a/app/services/libraries/refuse_apply_service.rb b/app/services/libraries/refuse_apply_service.rb new file mode 100644 index 00000000..5661773c --- /dev/null +++ b/app/services/libraries/refuse_apply_service.rb @@ -0,0 +1,37 @@ +class Libraries::RefuseApplyService + Error = Class.new(StandardError) + + attr_reader :library_apply, :library, :user, :params + + def initialize(library_apply, user, params) + @library_apply = library_apply + @library = library_apply.library + @user = user + @params = params + end + + def call + reason = params[:reason].to_s.strip + raise Error, '原因不能为空' if reason.blank? + raise Error, '该状态下不能进行此操作' unless library_apply.may_refuse? + + ActiveRecord::Base.transaction do + library_apply.reason = reason + library_apply.refused_at = Time.current + library_apply.refuse + library_apply.save! + + # 将消息改为已处理 + Tiding.where(container_id: library.id, container_type: 'Library', tiding_type: 'Apply', status: 0).update_all(status: 1) + notify_library_author! + end + end + + private + + def notify_library_author! + Tiding.create!(user_id: library.user_id, trigger_user_id: 1, + container_id: library.id, container_type: 'Library', + tiding_type: 'System', status: 2, extra: library_apply.reason) + end +end \ No newline at end of file diff --git a/app/services/libraries/save_service.rb b/app/services/libraries/save_service.rb new file mode 100644 index 00000000..3a81d379 --- /dev/null +++ b/app/services/libraries/save_service.rb @@ -0,0 +1,37 @@ +class Libraries::SaveService + Error = Class.new(StandardError) + + attr_reader :library, :user, :params + + def initialize(library, user, params) + @library = library + @user = user + @params = params + end + + def call + validate_params! + + if library.new_record? + library.user_id = user.id + library.generate_uuid + end + + attachment_ids = params.delete(:attachment_ids) + + ActiveRecord::Base.transaction do + library.assign_attributes(params) + library.save! + + Attachment.where(id: attachment_ids).update_all(container_id: library.id, container_type: 'Library') + end + + library + end + + private + + def validate_params! + raise Error, '附件不能为空' if params[:attachment_ids].blank? + end +end diff --git a/app/services/libraries/submit_service.rb b/app/services/libraries/submit_service.rb new file mode 100644 index 00000000..965ba673 --- /dev/null +++ b/app/services/libraries/submit_service.rb @@ -0,0 +1,31 @@ +class Libraries::SubmitService + Error = Class.new(StandardError) + + attr_reader :library + + def initialize(library) + @library = library + end + + def call + raise Error, '该状态下不能提交审核' unless library.may_submit? + + ActiveRecord::Base.transaction do + library.published_at = Time.current + library.submit + library.save! + + library.library_applies.create! + send_library_apply_notify! + end + end + + private + + def send_library_apply_notify! + Tiding.create!(user_id: 1, trigger_user_id: library.user_id, + container_id: library.id, container_type: 'Library', + tiding_type: 'Apply', status: 0) + Trustie::Sms.send(mobile: '18711011226', send_type:'publish_library' , name: '管理员') rescue nil + end +end \ No newline at end of file diff --git a/app/views/layouts/base_management.html.erb b/app/views/layouts/base_management.html.erb index 48fee5c4..891cf808 100644 --- a/app/views/layouts/base_management.html.erb +++ b/app/views/layouts/base_management.html.erb @@ -116,6 +116,7 @@
  • <%= link_to '单位审批', unit_managements_path %>
  • <%= link_to '实训发布', shixun_authorization_managements_path %>
  • <%= link_to '实训课程发布', subject_authorization_managements_path %>
  • +
  • <%= link_to '文库发布', library_applies_path(status: :pending) %>
  • 认证+ diff --git a/app/views/managements/library_applies/_library_apply_list.html.erb b/app/views/managements/library_applies/_library_apply_list.html.erb new file mode 100644 index 00000000..46fe1b54 --- /dev/null +++ b/app/views/managements/library_applies/_library_apply_list.html.erb @@ -0,0 +1,78 @@ +<% if @library_applies.present? %> + <% @library_applies.each do |apply| %> + <% user = apply.library.user %> + <% library = apply.library %> +
    + + <%= image_tag(url_to_avatar(user), :class => "fl with10 edu-ad-user", :alt => "头像", :width => "50", :height => "50" ) %> + +
    + +
    +
    + <% end %> +
    +
    +
      + <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => true, :flag => true, :is_new => true %> +
    +
    +
    +
    +<% else %> + <%= render :partial => "welcome/no_data" %> +<% end %> + + \ No newline at end of file diff --git a/app/views/managements/library_applies/index.html.erb b/app/views/managements/library_applies/index.html.erb new file mode 100644 index 00000000..6cef2418 --- /dev/null +++ b/app/views/managements/library_applies/index.html.erb @@ -0,0 +1,120 @@ +
    +
    +

    文库发布

    +
    +
    +
    +
      +
    • + <%= link_to "待审批", library_applies_path(status: :pending), class: 'tab_type', remote: true %> +
    • +
    • + <%= link_to "已审批", library_applies_path(status: [:refused, :agreed]), class: 'tab_type', remote: true %> +
    • +
    +
    +
    +
    +
    + + +
    +
    +
    + <%= render :partial => "managements/library_applies/library_apply_list"%> +
    +
    +
    + +
    +
    +

    + <%= link_to "全部", library_applies_path(status: [:refused, :agreed]), :class => "edu-filter-cir-grey mr5 fl font-12 active", :id => "library_all_authentication", :remote => true %> + <%= link_to "同意", library_applies_path(status: :agreed), :class => "edu-filter-cir-grey mr5 fl font-12", :id => "library_agree_authentication", :remote => true %> + <%= link_to "拒绝", library_applies_path(status: :refused), :class => "edu-filter-cir-grey mr5 fl font-12", :id => "library_reject_authentication", :remote => true %> +

    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + \ No newline at end of file diff --git a/app/views/managements/library_applies/index.js.erb b/app/views/managements/library_applies/index.js.erb new file mode 100644 index 00000000..aa6f932f --- /dev/null +++ b/app/views/managements/library_applies/index.js.erb @@ -0,0 +1,30 @@ +var nTabIcon_1 = $("#edu-tab-con-1"); +var nTabIcon_2 = $("#edu-tab-con-2"); +var nTabNav_1 = $("#edu-tab-nav-1"); +var nTabNav_2 = $("#edu-tab-nav-2"); +var nAudit = $("#library_all_authentication").parent(); + +<% if params[:status].to_s == 'pending' %> +$("#authentication_list").html("<%= j( render :partial => "managements/library_applies/library_apply_list" ) %>"); +nTabNav_1.addClass("background-orange"); +nTabNav_2.removeClass("background-orange"); +nTabIcon_1.show(); +nTabIcon_2.hide(); +<% else %> +$("#library_authentication_list").html("<%= j( render :partial => "managements/library_applies/library_apply_list" ) %>"); +nTabNav_1.removeClass("background-orange"); +nTabNav_2.addClass("background-orange"); +nTabIcon_1.hide(); +nTabIcon_2.show(); +/* -------------------------- 未审批(全部、同意、拒绝点击时动态样式) ------------------------------ */ +if(<%= params[:status].to_s == 'agreed' %>){ + nAudit.find(".active").removeClass("active"); + $("#library_agree_authentication").addClass("active"); +}else if(<%= params[:status].to_s == 'refused' %>){ + nAudit.find(".active").removeClass("active"); + $("#library_reject_authentication").addClass("active"); +}else{ + nAudit.find(".active").removeClass("active"); + $("#library_all_authentication").addClass("active"); +} +<% end %> \ No newline at end of file diff --git a/config/locales/libraries/zh.yml b/config/locales/libraries/zh.yml new file mode 100644 index 00000000..3004ecab --- /dev/null +++ b/config/locales/libraries/zh.yml @@ -0,0 +1,8 @@ +'zh': + activerecord: + models: + library: '文库' + attributes: + library: + title: '标题' + content: '描述' diff --git a/config/routes.rb b/config/routes.rb index 137a1231..6a053d70 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -730,6 +730,15 @@ RedmineApp::Application.routes.draw do ## oauth相关 get :school_data_grow, controller: 'managements::schools', action: 'data_grow' get :school_data_contrast, controller: 'managements::schools', action: 'data_contrast' get :school_statistics_xlsx, controller: 'managements::schools', action: 'statistics_xlsx' + + scope module: :managements do + resources :library_applies, only: [:index] do + member do + post :agree + post :refuse + end + end + end end end # Enable Grack support @@ -2649,6 +2658,10 @@ RedmineApp::Application.routes.draw do ## oauth相关 resource :sso, only: [:show, :create] + resources :libraries do + post :publish, on: :member + end + get '/:sub_dir_name', :to => 'org_subfields#show', :as => 'show_subfield_without_id' Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir| diff --git a/db/migrate/20190626004605_create_libraries.rb b/db/migrate/20190626004605_create_libraries.rb new file mode 100644 index 00000000..b782eacd --- /dev/null +++ b/db/migrate/20190626004605_create_libraries.rb @@ -0,0 +1,18 @@ +class CreateLibraries < ActiveRecord::Migration + def change + create_table :libraries do |t| + t.references :user + + t.string :title + t.text :content + t.string :uuid, unique: true + t.string :status + t.integer :visited_count + t.datetime :published_at + + t.timestamps + end + + add_index :libraries, :published_at + end +end diff --git a/db/migrate/20190626005624_create_library_applies.rb b/db/migrate/20190626005624_create_library_applies.rb new file mode 100644 index 00000000..990bfa38 --- /dev/null +++ b/db/migrate/20190626005624_create_library_applies.rb @@ -0,0 +1,14 @@ +class CreateLibraryApplies < ActiveRecord::Migration + def change + create_table :library_applies do |t| + t.references :library + t.string :status + t.string :reason + + t.datetime :refused_at + t.timestamps + end + + add_index :library_applies, :refused_at + end +end diff --git a/lib/trustie/sms/sms.rb b/lib/trustie/sms/sms.rb index 33584a0c..319de17c 100644 --- a/lib/trustie/sms/sms.rb +++ b/lib/trustie/sms/sms.rb @@ -57,6 +57,9 @@ module Trustie elsif send_type == "training_pay" params['text'] = "【计算机实践教学】亲爱的#{user_name}老师,您已经成功报名参与了11月24日--25日在深圳大学举办的全国软件工程实践教学案例与应用研讨会,请准时参加。(如有任何参会问题,请致电咨询会务联系人汤老师13099740868)" Rails.logger.info "#{params['text']}" + elsif send_type == 'publish_library' + params['text'] = "【Edu实训】亲爱的#{name},有新的文库发布申请,请尽快处理" + Rails.logger.info "#{params['text']}" end http = Net::HTTP.new(send_tpl_sms_uri.host, send_tpl_sms_uri.port)