library management

dev_library
p31729568 6 years ago
parent 088c9fc4a1
commit cefa6fa68b

@ -67,6 +67,9 @@ gem 'oauth2'
gem 'axlsx', '3.0.0.pre' gem 'axlsx', '3.0.0.pre'
gem 'axlsx_rails', '0.3.0' gem 'axlsx_rails', '0.3.0'
# state machine
gem 'aasm'
#Ruby 2.2+ has removed test/unit from the core library. #Ruby 2.2+ has removed test/unit from the core library.
if RUBY_VERSION>='2.2' if RUBY_VERSION>='2.2'
gem 'test-unit', '~> 3.0' gem 'test-unit', '~> 3.0'

@ -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

@ -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

@ -727,16 +727,17 @@ module ApplicationHelper
when 9 when 9
sub_type == 1 ? "实训留言列表" : "" sub_type == 1 ? "实训留言列表" : ""
when 10 when 10
sub_type == 1 ? "实名认证" : case sub_type
(sub_type == 2 ? "试用授权" : when 1 then '实名认证'
(sub_type == 3 ? "部门审批" : when 2 then '试用授权'
(sub_type == 4 ? "单位审批" : when 3 then '部门审批'
(sub_type == 5 ? "实训发布" : when 4 then '单位审批'
(sub_type == 6 ? "实训课程发布" : "职业认证") when 5 then '实训发布'
) when 6 then '实训课程发布'
) when 7 then '职业认证'
) when 8 then '文库发布'
) else '职业认证'
end
when 11 when 11
"工程认证+" "工程认证+"
when 12 when 12
@ -7430,6 +7431,8 @@ def tiding_url tiding
project_pull_requests_path(tiding.parent_container_id) project_pull_requests_path(tiding.parent_container_id)
when 'Department' when 'Department'
my_account_path my_account_path
when 'Library'
tiding.tiding_type == 'System' ? library_applies_path : library_path(tiding.container_id)
end end
end end

@ -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

@ -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

@ -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

@ -358,6 +358,14 @@ class Tiding < ActiveRecord::Base
" " " "
when 'Department' when 'Department'
"你选填的二级单位:#{self.container.try(:name)}(#{self.container.try(:school).name})因不符合规范,已被系统删除.请重新选择" "你选填的二级单位:#{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 ? "审核已通过" : "审核未通过,<br/>原因:#{extra}"
"你提交的发布文库申请:#{library.try(:name)}#{text}"
end
else else
logger.error "error type: 1" logger.error "error type: 1"
end end

@ -250,6 +250,7 @@ class User < Principal
has_many :ec_course_users has_many :ec_course_users
has_many :libraries, dependent: :destroy
##### #####
scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") } scope :logged, lambda { where("#{User.table_name}.status <> #{STATUS_ANONYMOUS}") }

@ -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

@ -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

@ -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

@ -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

@ -116,6 +116,7 @@
<li><%= link_to '单位审批', unit_managements_path %></li> <li><%= link_to '单位审批', unit_managements_path %></li>
<li><%= link_to '实训发布', shixun_authorization_managements_path %></li> <li><%= link_to '实训发布', shixun_authorization_managements_path %></li>
<li><%= link_to '实训课程发布', subject_authorization_managements_path %></li> <li><%= link_to '实训课程发布', subject_authorization_managements_path %></li>
<li><%= link_to '文库发布', library_applies_path(status: :pending) %></li>
</ul> </ul>
</li> </li>
<li class="fl edu-admin-nav-li edu-position"><a href="javascript:void(0);" class="edu-admin-nav-a">认证+</a> <li class="fl edu-admin-nav-li edu-position"><a href="javascript:void(0);" class="edu-admin-nav-a">认证+</a>

@ -0,0 +1,78 @@
<% if @library_applies.present? %>
<% @library_applies.each do |apply| %>
<% user = apply.library.user %>
<% library = apply.library %>
<div class="admin-con-box apply-<%= apply.id %> clearfix">
<a href="<%= user_path(user) %>" target="_blank" class="fl with10 edu-ad-user">
<%= image_tag(url_to_avatar(user), :class => "fl with10 edu-ad-user", :alt => "头像", :width => "50", :height => "50" ) %>
</a>
<div class="fl with90">
<ul>
<li class="clearfix mb5">
<a href="<%= user_path(user) %>" class="fl"><%= user.try(:show_real_name) %></a>
<span class="fl ml30 font-12 mt3 color-grey"><%= time_from_now(apply.created_at) %></span>
<% if apply.pending? %>
<a href="javascript:void(0);" class="fr color-orange" onclick="reject_library_authentication_reason(this);" >拒绝</a>
<a href="javascript:void(0);" class="fr mr15 color-orange" data-remote="true" onclick="library_authorization_gree('<%= apply.id %>');">同意</a>
<% else %>
<a href="javascript:void(0);" class="<%= apply.agreed? ? 'task-btn-green' : '' %> task-btn fr"><%= apply.agreed? ? "已同意" : "已拒绝" %></a>
<% end %>
</li>
<li class="clearfix mb10">
<%= link_to library.title, library_path(library), :target => "_blank" %>
<br>
<%= library.content[0..100] %>
</li>
<% if apply.pending? %>
<div class="undis">
<li class="clearfix edu-form-border mb10">
<label class="edu-form-label fl">原因:</label>
<input type="text" class="task-form-90 task-height-40 panel-box-sizing fl edu-form-noborder" placeholder="我得说点儿什么最多200个字符">
</li>
<li class="clearfix">
<a href="javascript:void(0);" class="task-btn task-btn-orange fr" onclick="library_submit_reject_reason('<%= apply.id %>', this);" >确定</a>
<a href="javascript:void(0);" class="task-btn fr mr10" onclick="library_hide_reject_reason(this);" >取消</a>
</li>
</div>
<% else %>
<% if apply.refused? %>
<li>原因:<span class="color-orange"><%= apply.reason %></span></li>
<% end %>
<% end %>
</ul>
</div>
</div>
<% end %>
<div class="mt20 mb20" style="text-align:center;">
<div class="pages_user_show" style="width:auto; display:inline-block;">
<ul id="homework_pository_ref_pages">
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false, :remote => true, :flag => true, :is_new => true %>
</ul>
<div class="cl"></div>
</div>
</div>
<% else %>
<%= render :partial => "welcome/no_data" %>
<% end %>
<script type="text/javascript">
function library_authorization_gree(id){
$.ajax({
url: '/managements/library_applies/' + id + '/agree',
type: 'post',
success: function(data){
if (data && data.status != -1) {
$('#authentication_list .admin-con-box.apply-' + id).remove();
if($('#authentication_list .admin-con-box').length < 5){
location.reload();
}
} else {
alert(data.message);
}
}
})
}
</script>

@ -0,0 +1,120 @@
<div class="edu-class-container mb15">
<div class="edu-con-top clearfix">
<p class="ml15 fl color-grey">文库发布</p>
</div>
<div class="edu-con-bg01 mt15">
<div class="edu-tab clearfix mb20">
<ul id="edu-tab-nav" class="border-bottom-orange">
<li id="edu-tab-nav-1" class="new-tab-nav background-orange" onclick="HoverLi(1);">
<%= link_to "待审批", library_applies_path(status: :pending), class: 'tab_type', remote: true %>
</li>
<li id="edu-tab-nav-2" class="new-tab-nav" onclick="HoverLi(2);">
<%= link_to "已审批", library_applies_path(status: [:refused, :agreed]), class: 'tab_type', remote: true %>
</li>
</ul>
<div class="cl"></div>
<div id="edu-tab-con-1">
<div class="mt10">
<div class="edu-position fr task-form-30 mb10 mr15">
<input class="task-form-100 panel-box-sizing" placeholder="输入文库标题、编号进行检索" type="text" id="search_name">
<a href="javascript:void(0);" class="edu-btn-search font-16 color-grey mt10" id="search"><i class="fa fa-search"></i></a>
</div>
<div class="cl"></div>
<div id="authentication_list" class="auth_table">
<%= render :partial => "managements/library_applies/library_apply_list"%>
</div>
</div>
</div>
<div id="edu-tab-con-2" class="undis">
<div class="mt10">
<p class="fl task-form-60 mt8 ml15 clearfix">
<%= 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 %>
</p>
<div class="edu-position fr task-form-30 mb10 fr mr15">
<input class="task-form-100 panel-box-sizing" placeholder="输入文库标题、编号进行检索" type="text" id="library_search_name">
<a href="javascript:void(0);" class="edu-btn-search font-16 color-grey mt10" id="library_search"><i class="fa fa-search"></i></a>
</div>
<div class="cl"></div>
<div id="library_authentication_list" class="auth_table">
</div>
</div>
</div>
<div class="cl"></div>
</div>
</div>
</div>
<script>
/* -------------------------- 拒绝 ------------------------------------ */
function reject_library_authentication_reason(nThis){
var reason = $(nThis).parent().parent().find('div');
reason.find("input").val("");
reason.toggle();
}
/* -------------------------- 取消 ------------------------------------ */
function library_hide_reject_reason(nThis){
var reason = $(nThis).parent().parent();
reason.find("input").val("");
reason.hide();
}
/* ------------------------- 提交拒绝原因 --------------------------------- */
function library_submit_reject_reason(id, nThis){
var nReason = $(nThis).parent().parent();
var reason = nReason.find("input").val();
if (reason == '') {
alert('请输入原因');
return;
}
$.ajax({
url: '/managements/library_applies/' + id + '/refuse',
type: 'post',
data: {reason: reason},
success: function(data){
if (data && data.status != -1) {
$('#authentication_list .admin-con-box.apply-' + id).remove();
if($('#authentication_list .admin-con-box').length < 5){
location.reload();
}
} else {
alert(data.message);
}
}
});
}
/* -------------------------- 按名字进行搜索(未审批) ----------------------------- */
$("#search").live("click", function(){
var iName = $("#search_name").val();
$.ajax({
url: "/managements/library_applies",
dataType: 'script',
data: { search: iName, status: 'pending' }
});
});
/* ------------------- 按名字进行搜索(已审批)-------------------- */
$("#library_search").live("click", function(){
var iName = $("#library_search_name").val();
var id = $("#library_all_authentication").parent().find(".active").attr("id");
var status = '';
if(id == "library_all_authentication"){
status = ['refused', 'agreed'];
}else if(id=="library_agree_authentication"){
status = 'agreed';
}else{
status = 'refused';
}
$.ajax({
url: "/managements/library_applies",
dataType: 'script',
data: { search: iName, status: status}
});
});
</script>

@ -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 %>

@ -0,0 +1,8 @@
'zh':
activerecord:
models:
library: '文库'
attributes:
library:
title: '标题'
content: '描述'

@ -730,6 +730,15 @@ RedmineApp::Application.routes.draw do ## oauth相关
get :school_data_grow, controller: 'managements::schools', action: 'data_grow' get :school_data_grow, controller: 'managements::schools', action: 'data_grow'
get :school_data_contrast, controller: 'managements::schools', action: 'data_contrast' get :school_data_contrast, controller: 'managements::schools', action: 'data_contrast'
get :school_statistics_xlsx, controller: 'managements::schools', action: 'statistics_xlsx' 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
end end
# Enable Grack support # Enable Grack support
@ -2649,6 +2658,10 @@ RedmineApp::Application.routes.draw do ## oauth相关
resource :sso, only: [:show, :create] 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' get '/:sub_dir_name', :to => 'org_subfields#show', :as => 'show_subfield_without_id'
Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir| Dir.glob File.expand_path("plugins/*", Rails.root) do |plugin_dir|

@ -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

@ -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

@ -57,6 +57,9 @@ module Trustie
elsif send_type == "training_pay" elsif send_type == "training_pay"
params['text'] = "【计算机实践教学】亲爱的#{user_name}老师您已经成功报名参与了11月24日--25日在深圳大学举办的全国软件工程实践教学案例与应用研讨会请准时参加。如有任何参会问题请致电咨询会务联系人汤老师13099740868" params['text'] = "【计算机实践教学】亲爱的#{user_name}老师您已经成功报名参与了11月24日--25日在深圳大学举办的全国软件工程实践教学案例与应用研讨会请准时参加。如有任何参会问题请致电咨询会务联系人汤老师13099740868"
Rails.logger.info "#{params['text']}" Rails.logger.info "#{params['text']}"
elsif send_type == 'publish_library'
params['text'] = "【Edu实训】亲爱的#{name},有新的文库发布申请,请尽快处理"
Rails.logger.info "#{params['text']}"
end end
http = Net::HTTP.new(send_tpl_sms_uri.host, send_tpl_sms_uri.port) http = Net::HTTP.new(send_tpl_sms_uri.host, send_tpl_sms_uri.port)

Loading…
Cancel
Save