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..4b73a246
--- /dev/null
+++ b/app/controllers/libraries_controller.rb
@@ -0,0 +1,105 @@
+class LibrariesController < ApplicationController
+ layout 'base_library'
+
+ before_filter :require_login
+
+ def index
+ libraries = Library.where(nil)
+
+ libraries =
+ if params[:type] == '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?
+
+ per_page = params[:per_page].to_i <= 0 ? 20 : params[:per_page].to_i
+ @libraries = paginateHelper libraries.includes(user: :user_extensions), per_page
+ end
+
+ def show
+ @library = Library.find(params[:id])
+ return redirect_to libraries_path unless admin_or_self?
+
+ @library_applies = @library.library_applies.where(status: :refused).order('created_at desc')
+ @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, form_params).call
+ if with_publish?
+ Libraries::SubmitService.new(current_library).call
+ redirect_to publish_success_libraries_path
+ else
+ flash[:message] = '保存成功'
+ render 'new'
+ end
+ rescue ActiveRecord::RecordInvalid => _
+ render 'new'
+ rescue Libraries::SubmitService::Error => ex
+ flash[:message] = ex.message
+ render 'new'
+ end
+
+ def edit
+ @library = current_library
+ redirect_to library_path(id: @library.id) unless @library.editable?
+ end
+
+ def update
+ @library = current_library
+ Libraries::SaveService.new(@library, current_user, form_params).call
+ if with_publish?
+ Libraries::SubmitService.new(current_library).call
+ redirect_to publish_success_libraries_path
+ else
+ flash[:message] = '保存成功'
+ render 'edit'
+ end
+ rescue ActiveRecord::RecordInvalid => _
+ render 'edit'
+ rescue Libraries::SubmitService::Error => ex
+ flash[:message] = ex.message
+ 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
+
+ def publish_success
+ end
+
+ private
+
+ def current_library
+ @_current_library ||= current_user.libraries.find(params[:id])
+ end
+
+ def form_params
+ @_form_params ||= begin
+ hash = params[:library].presence || {}
+ hash[:attachment_ids] = (params[:attachments].presence || []).values.map{|h| h[:attachment_id]}
+ hash
+ end
+ end
+
+ def with_publish?
+ params[:apply_publish].to_s == 'true'
+ end
+
+ def admin_or_self?
+ @library.user_id == current_user.id || current_user.admin?
+ 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 18473fbf..67a37a41 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -745,16 +745,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
@@ -7448,6 +7449,8 @@ def tiding_url tiding
project_pull_requests_path(tiding.parent_container_id)
when 'Department'
my_account_path
+ when 'Library'
+ tiding.tiding_type == 'Apply' ? 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..78bc7fc5
--- /dev/null
+++ b/app/models/library.rb
@@ -0,0 +1,52 @@
+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
+
+ acts_as_attachable
+
+ 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
+
+ def editable?
+ pending? || refused?
+ 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..91bcf0b9 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(:title)}"
+ elsif tiding_type == 'System'
+ text = status == 1 ? "审核已通过" : "审核未通过, 原因:#{extra}"
+ "你提交的发布文库申请:#{library.try(:title)},#{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..78fdbcb0
--- /dev/null
+++ b/app/services/libraries/refuse_apply_service.rb
@@ -0,0 +1,39 @@
+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!
+
+ library.refuse!
+
+ # 将消息改为已处理
+ 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/attachments/_from_libraries.html.erb b/app/views/attachments/_from_libraries.html.erb
new file mode 100644
index 00000000..4abb3c80
--- /dev/null
+++ b/app/views/attachments/_from_libraries.html.erb
@@ -0,0 +1,62 @@
+
+
+ 上传附件
+
+ 从我的电脑选择要上传的文档:按住CTRL可以上传多份文档
+ 上传出现错误,请检查您的网络环境,并刷新页面重新上传。
+
+
+
+ <% if defined?(container) && container && container.saved_attachments %>
+ <% container.attachments.each_with_index do |attachment, i| %>
+
+
+ <% size = judge_Chinese_num attachment.filename %>
+ <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'upload_filename readonly hidden color-grey fl', :size => size, :style => 'border:none; max-width:980px;white-space: nowrap; text-overflow:ellipsis;font-family: Consolas;', :readonly => 'readonly') %>
+ <%= number_to_human_size attachment.filesize %>
+ <%= link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload') unless attachment.id.nil? %>
+ <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
+
+ <% end %>
+ <% container.saved_attachments.each_with_index do |attachment, i| %>
+
+
+
+ <%= text_field_tag("attachments[p#{i}][filename]", attachment.filename, :class => 'hidden atta_input readonly color-grey fl', :style => 'border:none; max-width:980px;', :readonly => 'readonly') %>
+ <%= link_to(' '.html_safe, attachment_path(attachment, :attachment_id => "p#{i}", :format => 'js'), :method => 'delete', :remote => true, :class => 'remove-upload fl mt2') unless attachment.id.nil? %>
+ <%= hidden_field_tag "attachments[p#{i}][token]", "#{attachment.token}" %>
+
+ <% end %>
+ <% end %>
+
+<%= file_field_tag 'attachments[dummy][file]',
+ :id => '_file',
+ :class => ie8? ? '' : 'file_selector',
+ :multiple => true,
+ :onchange => 'addInputFiles(this);',
+ :style => ie8? ? '' : 'display:none',
+ :data => {
+ :max_file_size => Setting.attachment_max_size.to_i.kilobytes,
+ :max_file_size_message => l(:error_attachment_too_big, :max_size => number_to_human_size(Setting.attachment_max_size.to_i.kilobytes)),
+ :max_concurrent_uploads => Redmine::Configuration['max_concurrent_ajax_uploads'].to_i,
+ :upload_path => uploads_path(:format => 'js',:project =>nil),
+ :description_placeholder => l(:label_optional_description),
+ :field_is_public => l(:field_is_public),
+ :are_you_sure => l(:text_are_you_sure),
+ :file_count => l(:label_file_count),
+ :lebel_file_uploding => l(:lebel_file_uploding),
+ :delete_all_files => l(:text_are_you_sure_all)
+ } %>
+
+
+
+<%= javascript_include_tag 'attachments' %>
+
\ No newline at end of file
diff --git a/app/views/competitions/_qg_second_competition.html.erb b/app/views/competitions/_qg_second_competition.html.erb
new file mode 100644
index 00000000..da4aa51f
--- /dev/null
+++ b/app/views/competitions/_qg_second_competition.html.erb
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/views/layouts/_logined_header.html.erb b/app/views/layouts/_logined_header.html.erb
index 30ef0658..077ef249 100644
--- a/app/views/layouts/_logined_header.html.erb
+++ b/app/views/layouts/_logined_header.html.erb
@@ -25,6 +25,7 @@
<%= link_to "认证", department_ecs_path(:school_id => User.current.ec_school) %>
<% end %>
+ "><%= link_to '文库', libraries_path %>
diff --git a/app/views/layouts/base_library.html.erb b/app/views/layouts/base_library.html.erb
new file mode 100644
index 00000000..3eceefb6
--- /dev/null
+++ b/app/views/layouts/base_library.html.erb
@@ -0,0 +1,71 @@
+
+
+
+
+
+ <%= h html_title %>
+
+
+
+ <%= csrf_meta_tag %>
+ <%= favicon %>
+ <%= javascript_heads %>
+ <%= heads_for_theme %>
+ <%= call_hook :view_layouts_base_html_head %>
+ <%= stylesheet_link_tag 'jquery/jquery-ui-1.9.2', 'css/common', 'css/public', 'css/ketang', 'css/structure', 'prettify', 'css/courses', 'css/popup', 'css/syllabus', 'css/moduel', 'css/font-awesome', 'css/contest', 'css/font-awesome', 'css/edu-class', 'css/edu-popup', 'educoder/magic-check', 'css/edu-common', "css/edu-public", 'educoder/edu-main', 'educoder/edu-all' %>
+ <%= javascript_include_tag "avatars", "header", "attachments", 'prettify', "edu/application", 'jquery.datetimepicker.js', 'educoder/edu_application', 'educoder/edu_file' %>
+ <%= javascript_include_tag "/codemirror/lib/codemirror", "/codemirror/mode/javascript/javascript", "/codemirror/addon/hint/show-hint", "/codemirror/addon/hint/javascript-hint", "/codemirror/addon/selection/active-line", "/codemirror/addon/lint/javascript-lint", "/codemirror/addon/lint/css-lint", "/codemirror/addon/lint/lint", "/codemirror/addon/lint/json-lint", "/editormd/lib/codemirror/addon/lint/css-lint" %>
+ <%= stylesheet_link_tag "/codemirror/lib/codemirror" %>
+ <%= stylesheet_link_tag '/editormd/css/editormd' %>
+ <%= javascript_include_tag '/editormd/editormd', '/editormd/lib/marked.min.js', '/editormd/lib/prettify.min.js', '/editormd/lib/raphael.min.js', '/editormd/lib/underscore.min.js', '/editormd/lib/sequence-diagram.min.js',
+ '/editormd/lib/flowchart.min.js', '/editormd/lib/jquery.flowchart.min.js', '/editormd/editormd.js' %>
+ <%= yield :header_tags -%>
+
+
+
+
+
+
+
+
+
+
+ <%= yield %>
+
+ <%= render :partial => 'users/returnTop_btn' %>
+
+
+ <%#= render :partial => 'layouts/public_left_info' %>
+ <%= render :partial => 'layouts/footer' %>
+
+ <%#= render :partial => 'layouts/new_feedback' %>
+
+
+ <%= l(:label_loading) %>
+
+
+
+
+ <%= call_hook :view_layouts_base_body_bottom %>
+
+
+
+
\ 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/libraries/_form.html.erb b/app/views/libraries/_form.html.erb
new file mode 100644
index 00000000..6d4af4b3
--- /dev/null
+++ b/app/views/libraries/_form.html.erb
@@ -0,0 +1,115 @@
+上传文档
+
+
+
\ No newline at end of file
diff --git a/app/views/libraries/_library_list.html.erb b/app/views/libraries/_library_list.html.erb
new file mode 100644
index 00000000..e147e237
--- /dev/null
+++ b/app/views/libraries/_library_list.html.erb
@@ -0,0 +1,28 @@
+
+ <% if @libraries.present? %>
+ <% @libraries.each do |library| %>
+
+
+
+
<%= link_to library.title, library_path(library) %>
+
+ <%= link_to library.user.show_real_name, user_path(library.user) %>
+ <%= library.visited_count || 0 %> 浏览
+ 发布时间:<%= library.published_at.try(:strftime, '%Y-%m-%d %H:%M') %>
+
+
+
+ <% end %>
+ <% else %>
+ <%= render :partial => "welcome/no_data" %>
+ <% end %>
+
+
+
+
+
+ <%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => true, :flag => true, :is_new => true %>
+
+
+
+
\ No newline at end of file
diff --git a/app/views/libraries/edit.html.erb b/app/views/libraries/edit.html.erb
new file mode 100644
index 00000000..e258e1c1
--- /dev/null
+++ b/app/views/libraries/edit.html.erb
@@ -0,0 +1,8 @@
+
+
+ <%= link_to '文库', libraries_path, class: 'color-grey-9' %> >
+ 编辑
+
+
+ <%= render partial: 'form' %>
+
\ No newline at end of file
diff --git a/app/views/libraries/index.html.erb b/app/views/libraries/index.html.erb
new file mode 100644
index 00000000..98e80cb0
--- /dev/null
+++ b/app/views/libraries/index.html.erb
@@ -0,0 +1,51 @@
+
+
+
+ 文库
+ <%= link_to '新建', new_library_path, class: 'fr color-blue font-16 mt3' %>
+
+
+
+
+ <%= link_to '全部', libraries_path(search: params[:search]), remote: true %>
+
+
+ <%= link_to '我的', libraries_path(search: params[:search], type: 'mine'), remote: true %>
+
+
+
+ <%= hidden_field_tag(:type, params[:type]) %>
+
+
+
+
+
+
+ <%= render partial: 'library_list' %>
+
+
+
\ No newline at end of file
diff --git a/app/views/libraries/index.js.erb b/app/views/libraries/index.js.erb
new file mode 100644
index 00000000..78d48f8f
--- /dev/null
+++ b/app/views/libraries/index.js.erb
@@ -0,0 +1,3 @@
+$('input[name="type"]').val('<%= params[:type].to_s %>');
+$('#search_name').val('<%= params[:search].to_s %>');
+$('.library-list-container').html('<%= j render(partial: 'library_list') %>')
\ No newline at end of file
diff --git a/app/views/libraries/new.html.erb b/app/views/libraries/new.html.erb
new file mode 100644
index 00000000..987951d3
--- /dev/null
+++ b/app/views/libraries/new.html.erb
@@ -0,0 +1,8 @@
+
+
+ <%= link_to '文库', libraries_path, class: 'color-grey-9' %> >
+ 新建
+
+
+ <%= render partial: 'form' %>
+
\ No newline at end of file
diff --git a/app/views/libraries/publish_success.html.erb b/app/views/libraries/publish_success.html.erb
new file mode 100644
index 00000000..372053e6
--- /dev/null
+++ b/app/views/libraries/publish_success.html.erb
@@ -0,0 +1,14 @@
+
+
+
+
+
通过平台管理员审核后,即可公开显示
+
+ <%= link_to '查看已上传文档', libraries_path(type: 'mine'), class: 'white-btn edu-blueline-btn changebtn mr20 fl' %>
+ <%= link_to '继续上传', new_library_path, class: 'white-btn edu-blueback-btn changebtn fl' %>
+
+
+
\ No newline at end of file
diff --git a/app/views/libraries/show.html.erb b/app/views/libraries/show.html.erb
new file mode 100644
index 00000000..1c23d979
--- /dev/null
+++ b/app/views/libraries/show.html.erb
@@ -0,0 +1,92 @@
+<%
+ admin_or_self = User.current.admin? || @library.user_id == User.current.id
+%>
+
+
+ <%= link_to '文库', libraries_path, class: 'color-grey-9' %> >
+ 详情
+
+
+ <%= @library.title %>
+ <% if admin_or_self %>
+ <% if @library.pending? %>
+ 草稿
+ <% elsif @library.processing? %>
+ 审核中
+ <% elsif @library.refused? %>
+ 未通过
+ <% end %>
+ <% end %>
+ <%= link_to('返回', libraries_path, class: 'fr color-grey-9 mt5') %>
+
+
+ <% if admin_or_self && !@library.published? && @library_applies.size > 0 %>
+
+
+ 私有化原因
+ (请按照提示修改,并在完成编辑后重新提交)
+ 点击展开
+
+
+ <% @library_applies.each do |apply| %>
+
+ <%= apply.updated_at.strftime('%Y-%m-%d %H:%M') %>
+ <%= apply.reason %>
+
+ <% end %>
+
+
+ <% end %>
+
+
+ 详情
+ <% if admin_or_self && @library.editable? %>
+ <%= link_to '编辑', edit_library_path(id: @library.id), class: 'white-btn edu-blueline-btn fr' %>
+ <% end %>
+
+
+
+
+
<%= @library.user.show_real_name %>
+
+ <%= @library.user.school_name %>
+ <%= @library.user.identity %>
+
+ 编码:<%= @library.uuid %>
+ 上传时间:<%= @library.created_at.strftime('%Y-%m-%d %H:%M') %>
+
+
+
+
+
+
+
+
+
+ <%= render partial: 'attachments/links', locals: { attachments: @library.attachments, options: {} } %>
+
+
+
+
+
+
\ No newline at end of file
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..81e6c1d4
--- /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 %>
+
+ <% 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..23d898c4
--- /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..5d523390 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
+ get :publish_success, on: :collection
+ 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..07e9c1d8
--- /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, default: 0
+ 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)
diff --git a/public/images/educoder/competition/qg/qg_two_1.png b/public/images/educoder/competition/qg/qg_two_1.png
new file mode 100644
index 00000000..a8dab761
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_1.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_2.png b/public/images/educoder/competition/qg/qg_two_2.png
new file mode 100644
index 00000000..fe7daae9
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_2.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_3.png b/public/images/educoder/competition/qg/qg_two_3.png
new file mode 100644
index 00000000..feea3642
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_3.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_4.png b/public/images/educoder/competition/qg/qg_two_4.png
new file mode 100644
index 00000000..07e6d90d
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_4.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_5.png b/public/images/educoder/competition/qg/qg_two_5.png
new file mode 100644
index 00000000..55b68d40
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_5.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_6.png b/public/images/educoder/competition/qg/qg_two_6.png
new file mode 100644
index 00000000..96507a72
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_6.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_7.png b/public/images/educoder/competition/qg/qg_two_7.png
new file mode 100644
index 00000000..33e65de1
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_7.png differ
diff --git a/public/images/educoder/competition/qg/qg_two_8.png b/public/images/educoder/competition/qg/qg_two_8.png
new file mode 100644
index 00000000..50016195
Binary files /dev/null and b/public/images/educoder/competition/qg/qg_two_8.png differ
diff --git a/public/images/educoder/success.png b/public/images/educoder/success.png
new file mode 100644
index 00000000..9282ef4d
Binary files /dev/null and b/public/images/educoder/success.png differ
diff --git a/public/stylesheets/educoder/edu-all.css b/public/stylesheets/educoder/edu-all.css
index bbd05a56..7415399c 100644
--- a/public/stylesheets/educoder/edu-all.css
+++ b/public/stylesheets/educoder/edu-all.css
@@ -602,7 +602,7 @@ p .activity-item:first-child{border-top: 1px solid #eee;}
#competition-content img,#competition-db-content img,#ccfPage img{vertical-align: bottom;}
#hnpage1{background: url('/images/educoder/competition/logo_1.jpg') no-repeat top center;min-height: 820px;}
-#competition-header{background: linear-gradient(to right, #29bd8b , #13dc98);height: 60px;width: 100%;padding-right: 40px;box-sizing: border-box;position: fixed;top: 0px;left: 0px;width: 100%;z-index: 1000;}
+#competition-header{background:#24292D;height: 60px;width: 100%;padding-right: 40px;box-sizing: border-box;position: fixed;top: 0px;left: 0px;width: 100%;z-index: 1000;}
.nav-game{position: relative;}
.nav-game li{position: relative;float: left;width: 110px;height: 60px;line-height: 60px;text-align: center;box-sizing: border-box}
.nav-game li a{color:#fff;font-size: 16px;}
@@ -639,6 +639,29 @@ a.enterLink{cursor: pointer;color: #418CCD!important;background: none!important;
.position-shixun{position: absolute;z-index: 2;bottom: 40px;text-align: center;width: 100%}
.ccf-position-shixun .shixun-btn,.position-shixun .shixun-btn,.ccf-position-shixun-2 .shixun-btn{display: block;float: left;width: 160px;text-align:center;letter-spacing: 1px;height: 40px;line-height: 40px;color:#fff!important;margin:0px 20px;background: linear-gradient(to right, #ff8634 , #ff9d5b);box-shadow: 6px 4px 11px #f7ece4;}
+/*第二次竞赛-全国*/
+.second_1{min-height: 832px;}
+.second_2{min-height: 446px;}
+.second_3{min-height: 595px;padding-top: 190px;box-sizing: border-box;position: relative}
+.second_4{min-height: 610px;padding-top: 190px;box-sizing: border-box;position: relative}
+.second_5{min-height: 617px;padding-top: 190px;box-sizing: border-box;position: relative}
+.second_6{min-height: 1053px;}
+.second_7{min-height: 1096px;}
+.second_8{min-height: 727px;}
+.enter_panel{
+ width: 1200px;margin:0px auto;height: 360px;text-align: center;
+}
+.enter_title{
+ color: #0B8298;
+}
+.enter_btn a{
+ float: left;width: 300px;height: 60px;background: #ccc;color: #fff!important;margin:0px 35px;line-height: 60px;
+ font-size: 22px;font-weight: bold;border-radius: 2px;
+}
+.enter_btn a.active{
+ background: #DAECFC;color: #2BC4C6!important;
+}
+.enter_btn a.active:hover{background: #2CDAD4;color: #fff!important;}
@media screen and (max-width: 1600px) {
@@ -3249,4 +3272,40 @@ line-height: 16px;display: inline-block;color: rgba(65, 140, 205, 1) !important;
position:absolute;
top: 12px;
right: 20px;
+}
+
+/*文库*/
+.library_nav li{
+ float: left;cursor: pointer;margin-right: 30px;position: relative;color: #05101A;height: 40px;line-height: 20px;
+ font-size: 16px;
+}
+.library_nav li.active,.library_nav li:hover{
+ color: #4cacff;
+}
+.library_nav li.active:after{
+ position: absolute;content: '';background: #4cacff;color: #4cacff;width: 100%;height: 2px;bottom: 0px;left:0px;
+}
+.library_list{
+ margin-bottom: 30px;
+}
+.library_list_item{
+ background: #fff;padding:30px;margin-bottom: 15px;display: flex;
+}
+.upload_Title{
+ position: relative;margin-right: 30px;float: left;line-height: 35px;font-size: 16px;
+}
+.upload_Title:before{
+ position: absolute;left: -10px;top:2px;content: '*';color: #FE4F4C;
+}
+.librariesField{
+ width: 100%;background: #F2F9FF;justify-content: center;align-items: center;display: -webkit-flex;text-align: center;
+ height: 120px;border-radius: 4px;border:1px dashed #4cacff;
+}
+.private_reason{overflow: hidden;max-height:150px;}
+.private_reason li{margin-bottom: 10px;}
+.successPage{
+ justify-content: center;align-items: center;display: -webkit-flex;height: 570px;text-align: center;margin-bottom: 50px;
+}
+.changebtn{
+ width: 127px;font-size: 16px;height: 40px; line-height: 40px;
}
\ No newline at end of file
diff --git a/public/stylesheets/educoder/edu-main.css b/public/stylesheets/educoder/edu-main.css
index 266f9b7f..fca9b02b 100644
--- a/public/stylesheets/educoder/edu-main.css
+++ b/public/stylesheets/educoder/edu-main.css
@@ -180,7 +180,7 @@ a.decoration{text-decoration: underline}
/*定位*/
.pr{position: relative}
.df {display:flex;display: -webkit-flex;display: -ms-flex;}
-.flex1{flex: 1;}
+.flex1{flex: 1;width: 0}
/*去掉IE input框输入时自带的清除按钮*/
input::-ms-clear{display:none;}
/*自定义滚动条宽度*/
@@ -529,6 +529,10 @@ a.edu-blueback-btn{padding: 0px 10px;background: #4CACFF;color: #fff!important;b
a.edu-blueline-btn{padding: 0px 10px;color: #4CACFF!important;border: 1px solid #4CACFF;}
a.edu-blueback-btn:hover{background-color: #459BE6;}
a.edu-blueline-btn:hover{border:1px solid #459BE6;color: #459BE6!important;}
+input.edu-blueback-btn{padding: 0px 10px;background: #4CACFF;color: #fff!important;border: 1px solid #4CACFF;}
+input.edu-blueline-btn{padding: 0px 10px;color: #4CACFF!important;border: 1px solid #4CACFF;}
+input.edu-blueback-btn:hover{background-color: #459BE6;}
+input.edu-blueline-btn:hover{border:1px solid #459BE6;color: #459BE6!important;}
a.edu-orangeback-btn{background-color: #ff7500;color: #fff!important;border:1px solid #FF7500}
a.edu-orangeback-btn:hover{background-color: #F06200;}