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 "全部", 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 %> +
+ + +