diff --git a/Gemfile b/Gemfile index 3027c16cd..a67fcfaea 100644 --- a/Gemfile +++ b/Gemfile @@ -30,6 +30,13 @@ gem 'rails_kindeditor',path:'lib/rails_kindeditor' #gem "rmagick", ">= 2.0.0" gem 'binding_of_caller' gem 'chinese_pinyin' +# gem 'sunspot_rails', '~> 1.3.3' +# gem 'sunspot_solr' +# gem 'sunspot' +# gem 'progress_bar' +gem 'kaminari' +gem 'elasticsearch-model' +gem 'elasticsearch-rails' group :development do gem 'grape-swagger' diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 776e6b7d5..8188ce12e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1856,7 +1856,7 @@ class UsersController < ApplicationController # 根据资源关键字进行搜索 def resource_search search = params[:search].to_s.strip.downcase - if(params[:type].nil? || params[:type] == "1") #全部 + if(params[:type].nil? || params[:type].blank? || params[:type] == "1") #全部 if User.current.id.to_i == params[:id].to_i user_course_ids = User.current.courses.map { |c| c.id} #我的资源库的话,那么应该是我上传的所有资源 加上 我加入的课程的所有资源 取交集并查询 @attachments = Attachment.where("((author_id = #{params[:id]} and container_type in('Project','Principal','Course','Issue','Document','Message','News','StudentWorkScore','HomewCommon')) "+ diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index 784066378..4b75a3297 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -151,36 +151,101 @@ class WelcomeController < ApplicationController end def search - search_condition = params[:q] - search_type = params[:search_type].to_sym unless search_condition.blank? - search_by = params[:search_by] + @name = params[:q] + @search_type = params[:search_type] + case params[:search_type] + when 'all' + @alls = Elasticsearch::Model.search({ + query: { + multi_match: { + query: @name, + type:"most_fields", + fields: ['login^5', 'firstname','lastname','name^5','description','filename^5'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + login: {}, + firstname: {}, + lastname: {}, + name:{}, + description:{}, + filename:{} + } + } + },[User,Course,Attachment,Project] ).page(params[:page] || 1).per(20).results + when 'user' + @users = User.search(@name).page(params[:page] || 1).per(20) + when 'project' + @projects = Project.search(@name).page(params[:page] || 1).per(20).results + when 'course' + @courses = Course.search(@name).page(params[:page] || 1).per(20).results + when 'attachment' + @attachments = Attachment.search(@name).page(params[:page] || 1).per(20).results + else + @alls = Elasticsearch::Model.search({ + query: { + multi_match: { + query: @name, + type:"most_fields", + fields: ['login^5', 'firstname','lastname','name^5','description','filename^5'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + login: {}, + firstname: {}, + lastname: {}, + name:{}, + description:{}, + filename:{} + } + } + },[User,Course,Attachment,Project] ).page(params[:page] || 1).per(20).results - if search_type.nil? && params[:contests_search] && params[:name] != "" - search_type = :contests - search_condition = params[:name] end + @users_count = User.search(@name).results.total + + @course_count = Course.search(@name).results.total + @attach_count = Attachment.search(@name).results.total + @project_count = Project.search(@name).results.total + @total_count = Elasticsearch::Model.search({ + query: { + multi_match: { + query: @name, + type:"most_fields", + fields: ['login^5', 'firstname','lastname','name^5','description','filename^5'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + login: {}, + firstname: {}, + lastname: {}, + name:{}, + description:{}, + filename:{} + } + } + },[User,Course,Attachment,Project] ).results.total + # search_type = params[:search_type].to_sym unless search_condition.blank? + # search_by = params[:search_by] + # + # if search_type.nil? && params[:contests_search] && params[:name] != "" + # search_type = :contests + # search_condition = params[:name] + # end + respond_to do |format| - format.html{ - case search_type - when :projects - redirect_to projects_search_url(:name => search_condition, - :project_type => Project::ProjectType_project) - when :courses - redirect_to courses_search_url(:name => search_condition) - when :contests - redirect_to contests_url(:name => search_condition) - when :users - redirect_to users_search_url(:name => search_condition,:search_by => search_by) - when :users_teacher - redirect_to users_search_url(:name => search_condition, :search_by => search_by, :role => :teacher) - when :users_student - redirect_to users_search_url(:name => search_condition, :search_by => search_by, :role => :student) - else - #redirect_to home_path, :alert => l(:label_sumbit_empty) - (redirect_to signin_path, :notice => l(:label_sumbit_empty);return) #if params[:name].blank? - end - } + format.js + format.html{ render :layout=>'users_base'} end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index f4e0f88ff..15e29f39c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1825,6 +1825,23 @@ module ApplicationHelper s end + def get_user_identity identity + s = "" + case identity + when 0 + s = '教师' + when 1 + s = '学生' + when 2 + s = '组织' + when 3 + s= '开发者' + else + s = '学生' + end + s + end + def get_memo @new_memo = Memo.new @public_forum = Forum.find(1) rescue ActiveRecord::RecordNotFound diff --git a/app/models/attachment.rb b/app/models/attachment.rb index f7fb9b1aa..a98111b4f 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -17,7 +17,7 @@ require "digest/md5" require "fileutils" - +require 'elasticsearch/model' class Attachment < ActiveRecord::Base belongs_to :container, :polymorphic => true belongs_to :project, foreign_key: 'container_id', conditions: "attachments.container_type = 'Project'" @@ -38,6 +38,17 @@ class Attachment < ActiveRecord::Base validates :description, length: {maximum: 254} validate :validate_max_file_size + #elasticsearch + include Elasticsearch::Model + #elasticsearch kaminari init + Kaminari::Hooks.init + Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari + settings index: { number_of_shards: 1 } do + mappings dynamic: 'false' do + indexes :filename, analyzer: 'smartcn',index_options: 'offsets' + end + end + acts_as_taggable acts_as_event :title => :filename, @@ -74,9 +85,9 @@ class Attachment < ActiveRecord::Base @@thumbnails_storage_path = File.join(Rails.root, "tmp", "thumbnails") before_save :files_to_final_location,:act_as_course_activity - after_create :office_conver, :be_user_score,:act_as_forge_activity - after_update :office_conver, :be_user_score - after_destroy :delete_from_disk,:down_user_score + after_create :office_conver, :be_user_score,:act_as_forge_activity,:create_attachment_ealasticsearch_index + after_update :office_conver, :be_user_score,:update_attachment_ealasticsearch_index + after_destroy :delete_from_disk,:down_user_score,:delete_attachment_ealasticsearch_index # add by nwb # 获取所有可公开的资源文件列表 @@ -92,7 +103,25 @@ class Attachment < ActiveRecord::Base " LEFT JOIN #{News.table_name} ON #{Attachment.table_name}.container_type='News' AND (#{News.table_name}.project_id in "+self.public_project_id + " OR #{News.table_name}.course_id in " + self.public_course_id + ")" + " LEFT JOIN #{HomeworkAttach.table_name} ON #{Attachment.table_name}.container_type='HomeworkAttach' AND #{HomeworkAttach.table_name}.bid_id in "+self.public_bid_id) } - + def self.search(query) + __elasticsearch__.search( + { + query: { + multi_match: { + query: query, + fields: ['filename'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + filename: {} + } + } + } + ) + end # add by nwb # 公开的项目id列表 def self.public_project_id @@ -560,4 +589,40 @@ class Attachment < ActiveRecord::Base self.course_acts << CourseActivity.new(:user_id => self.author_id,:course_id => self.container_id) end end + + def create_attachment_ealasticsearch_index + if self.is_public == 1 && ( (self.container_type == 'Project' && Project.find(self.container_id).is_public == 1) || + ( self.container_type == 'Course' && Course.find(self.container_id).is_public == 1) || + self.container_type == 'Principal') + self.__elasticsearch__.index_document + end + end + def update_attachment_ealasticsearch_index + if self.is_public == 1 && ( (self.container_type == 'Project' && Project.find(self.container_id).is_public == 1) || + ( self.container_type == 'Course' && Course.find(self.container_id).is_public == 1) || + self.container_type == 'Principal') + self.__elasticsearch__.update_document + end + end + def delete_attachment_ealasticsearch_index + if self.is_public == 1 && ( (self.container_type == 'Project' && Project.find(self.container_id).is_public == 1) || + ( self.container_type == 'Course' && Course.find(self.container_id).is_public == 1) || + self.container_type == 'Principal') + self.__elasticsearch__.delete_document + end + end end + +# Delete the previous articles index in Elasticsearch +# Attachment.__elasticsearch__.client.indices.delete index: Attachment.index_name rescue nil +# +# # Create the new index with the new mapping +# Attachment.__elasticsearch__.client.indices.create \ +# index: Attachment.index_name, +# body: { settings: Attachment.settings.to_hash, mappings: Attachment.mappings.to_hash } + +# Index all article records from the DB to Elasticsearch +#暂时只做公开课程/项目里的公开资源 和其他的公开资源 +Attachment.where('is_public = 1 and ((container_type in ("Principal")) ' + + 'or (container_type = "Course" and container_id in( SELECT `courses`.id FROM `courses` WHERE (courses.status <> 9 AND courses.is_public = 1)) )'+ + 'or (container_type = "Project" and container_id in(SELECT `projects`.id FROM `projects` WHERE (projects.status <> 9 AND projects.is_public = 1) ))' +')').import diff --git a/app/models/course.rb b/app/models/course.rb index 7288c3b3b..1991c00cb 100644 --- a/app/models/course.rb +++ b/app/models/course.rb @@ -1,10 +1,23 @@ - +require 'elasticsearch/model' class Course < ActiveRecord::Base include Redmine::SafeAttributes STATUS_ACTIVE = 1 STATUS_CLOSED = 5 STATUS_ARCHIVED = 9 + + #elasticsearch + include Elasticsearch::Model + + #elasticsearch kaminari init + Kaminari::Hooks.init + Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari + settings index: { number_of_shards: 1 } do + mappings dynamic: 'false' do + indexes :name, analyzer: 'smartcn',index_options: 'offsets' + indexes :description, analyzer: 'smartcn',index_options: 'offsets' + end + end attr_accessible :code, :extra, :name, :state, :tea_id, :time , :location, :state, :term, :password,:is_public,:description,:class_period, :open_student, :enterprise_name #belongs_to :project, :class_name => 'Course', :foreign_key => :extra, primary_key: :identifier @@ -51,9 +64,9 @@ class Course < ActiveRecord::Base validates_length_of :description, :maximum => 10000 before_save :self_validate # 公开课程变成私有课程,所有资源都变成私有 - after_update :update_files_public - after_create :create_board_sync, :act_as_course_activity, :act_as_course_message - before_destroy :delete_all_members + after_update :update_files_public,:update_course_ealasticsearch_index + after_create :create_board_sync, :act_as_course_activity, :act_as_course_message,:create_course_ealasticsearch_index + before_destroy :delete_all_members,:delete_course_ealasticsearch_index safe_attributes 'extra', 'time', @@ -96,6 +109,27 @@ class Course < ActiveRecord::Base end } + def self.search(query) + __elasticsearch__.search( + { + query: { + multi_match: { + query: query, + fields: ['name', 'description'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + name: {}, + description: {} + } + } + } + ) + end + def visible?(user=User.current) user.allowed_to?(:view_course, self) end @@ -339,6 +373,38 @@ class Course < ActiveRecord::Base #def name # read_attribute('name') || Project.find_by_identifier(self.extra).try(:name) #end + + # after_commit on: [:create] do + # __elasticsearch__.index_document + # end + # + # after_commit on: [:update] do + # __elasticsearch__.update_document + # end + # + # after_commit on: [:destroy] do + # __elasticsearch__.delete_document + # end + def create_course_ealasticsearch_index + self.__elasticsearch__.index_document + end + def update_course_ealasticsearch_index + self.__elasticsearch__.update_document + end + def delete_course_ealasticsearch_index + self.__elasticsearch__.delete_document + end end +# Delete the previous articles index in Elasticsearch +# Course.__elasticsearch__.client.indices.delete index: Course.index_name rescue nil +# +# # Create the new index with the new mapping +# Course.__elasticsearch__.client.indices.create \ +# index: Course.index_name, +# body: { settings: Course.settings.to_hash, mappings: Course.mappings.to_hash } + +# Index all article records from the DB to Elasticsearch +Course.import + diff --git a/app/models/project.rb b/app/models/project.rb index 0b0420920..53e909776 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +require 'elasticsearch/model' class Project < ActiveRecord::Base include Redmine::SafeAttributes ProjectType_project = 0 @@ -30,6 +30,18 @@ class Project < ActiveRecord::Base # Specific overidden Activities + #elasticsearch + include Elasticsearch::Model + #elasticsearch kaminari init + Kaminari::Hooks.init + Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari + settings index: { number_of_shards: 1 } do + mappings dynamic: 'false' do + indexes :name, analyzer: 'smartcn',index_options: 'offsets' + indexes :description, analyzer: 'smartcn',index_options: 'offsets' + end + end + has_many :student_works has_many :time_entry_activities has_many :members, :include => [:principal, :roles], :conditions => "#{Principal.table_name}.type='User' AND #{Principal.table_name}.status=#{Principal::STATUS_ACTIVE}" @@ -138,8 +150,9 @@ class Project < ActiveRecord::Base #ActiveModel::Dirty 这里有一个changed方法。对任何对象都可以用 after_save :update_inherited_members, :if => Proc.new {|project| project.inherit_members_changed?} # 创建project之后默认创建一个board,之后的board去掉了board的概念 - after_create :create_board_sync,:acts_as_forge_activities - before_destroy :delete_all_members + after_create :create_board_sync,:acts_as_forge_activities,:create_project_ealasticsearch_index + before_destroy :delete_all_members,:delete_project_ealasticsearch_index + after_update :update_project_ealasticsearch_index def remove_references_before_destroy return if self.id.nil? Watcher.delete_all ['watchable_id = ?', id] @@ -172,7 +185,27 @@ class Project < ActiveRecord::Base } scope :project_entities, -> { where(project_type: ProjectType_project) } scope :course_entities, -> { where(project_type: ProjectType_course) } - + + def self.search(query) + __elasticsearch__.search( + { + query: { + multi_match: { + query: query, + fields: ['name','description'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + name: {}, + description: {} + } + } + } + ) + end def new_course self.where('project_type = ?', 1) end @@ -1176,5 +1209,18 @@ class Project < ActiveRecord::Base end + def create_project_ealasticsearch_index + self.__elasticsearch__.index_document + end + def update_project_ealasticsearch_index + self.__elasticsearch__.update_document + end + def delete_project_ealasticsearch_index + self.__elasticsearch__.delete_document + end + + end +Project.import + diff --git a/app/models/user.rb b/app/models/user.rb index 85b9e2591..3818e5d47 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require "digest/sha1" - +require 'elasticsearch/model' class User < Principal TEACHER = 0 STUDENT = 1 @@ -25,6 +25,19 @@ class User < Principal include Redmine::SafeAttributes seems_rateable_rater + #elasticsearch + include Elasticsearch::Model + #elasticsearch kaminari init + Kaminari::Hooks.init + Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari + settings index: { number_of_shards: 1 } do + mappings dynamic: 'false' do + indexes :login, analyzer: 'smartcn',index_options: 'offsets' + indexes :firstname, analyzer: 'smartcn',index_options: 'offsets' + indexes :lastname, analyzer: 'smartcn',index_options: 'offsets' + end + end + # Different ways of displaying/sorting users USER_FORMATS = { :firstname_lastname => { @@ -64,6 +77,7 @@ class User < Principal }, } + #每日一报、一事一报、不报 MAIL_NOTIFICATION_OPTIONS = [ #['week', :label_user_mail_option_week], @@ -154,6 +168,7 @@ class User < Principal ##### has_many :shares ,:dependent => :destroy + # add by zjc has_one :level, :class_name => 'UserLevels', :dependent => :destroy has_many :memos , :foreign_key => 'author_id' @@ -214,12 +229,12 @@ class User < Principal # validates_email_realness_of :mail before_create :set_mail_notification before_save :update_hashed_password - before_destroy :remove_references_before_destroy + before_destroy :remove_references_before_destroy,:delete_user_ealasticsearch_index # added by fq - after_create :act_as_activity, :add_onclick_time, :act_as_principal_activity + after_create :act_as_activity, :add_onclick_time, :act_as_principal_activity,:create_user_ealasticsearch_index # end # 更新邮箱用户或用户名的同事,同步更新邀请信息 - after_update :update_invite_list + after_update :update_invite_list,:upadte_user_ealasticsearch_index include Trustie::Gitlab::ManageUser @@ -250,7 +265,27 @@ class User < Principal end end } - + def self.search(query) + __elasticsearch__.search( + { + query: { + multi_match: { + query: query, + fields: ['login', 'firstname','lastname'] + } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + login: {}, + firstname: {}, + lastname: {} + } + } + } + ) + end # ====================================================================== @@ -1145,4 +1180,32 @@ class AnonymousUser < User def destroy false end + + def create_user_ealasticsearch_index + if self.id != 2 && self.id != 4 + self.__elasticsearch__.index_document + end + end + def update_user_ealasticsearch_index + if self.id != 2 && self.id != 4 + self.__elasticsearch__.update_document + end + end + def delete_user_ealasticsearch_index + if self.id != 2 && self.id != 4 + self.__elasticsearch__.delete_document + end + end end + +# Delete the previous articles index in Elasticsearch +# User.__elasticsearch__.client.indices.delete index: User.index_name rescue nil +# +# # Create the new index with the new mapping +# User.__elasticsearch__.client.indices.create \ +# index: User.index_name, +# body: { settings: User.settings.to_hash, mappings: User.mappings.to_hash } + +# Index all article records from the DB to Elasticsearch +# 匿名用户 角色 和 管理员角色不能被索引 +User.where('id not in (2,4)').import diff --git a/app/views/kaminari/_paginator.html.erb b/app/views/kaminari/_paginator.html.erb index b4d5ee4ea..9a2a02ab9 100644 --- a/app/views/kaminari/_paginator.html.erb +++ b/app/views/kaminari/_paginator.html.erb @@ -8,7 +8,6 @@ -%> <%= paginator.render do -%> + +
+
+
+ + +
+ +
+
+ <%#= render :partial => 'search_user_results',:locals => {:users=>@users}%> +
+
+
+
+ +
+
+ +
+
+
+
diff --git a/app/views/welcome/search.js.erb b/app/views/welcome/search.js.erb new file mode 100644 index 000000000..c53c5d219 --- /dev/null +++ b/app/views/welcome/search.js.erb @@ -0,0 +1,13 @@ +<% case @search_type%> +<% when 'all'%> +$("#searchContent_1").html('<%= escape_javascript(render :partial => 'search_all_results',:locals => {:all_results=> @alls})%>'); +<% when 'user'%> +$("#searchContent_2").html('<%= escape_javascript(render :partial => 'search_user_results',:locals => {:users=>@users})%>'); +<% when 'course'%> +$("#searchContent_3").html('<%= escape_javascript(render :partial => 'search_course_results',:locals => {:courses=>@courses})%>'); +<% when 'project'%> +$("#searchContent_5").html('<%= escape_javascript(render :partial => 'search_project_results',:locals => {:projects=>@projects})%>'); +<% when 'attachment'%> +$("#searchContent_4").html('<%= escape_javascript(render :partial => 'search_attachment_results',:locals => {:attachments=>@attachments})%>'); +<%else%> +<%end %> \ No newline at end of file diff --git a/config/initializers/kaminari_config.rb b/config/initializers/kaminari_config.rb index 1f07c0af5..5d1c9b6ad 100644 --- a/config/initializers/kaminari_config.rb +++ b/config/initializers/kaminari_config.rb @@ -23,10 +23,10 @@ Kaminari.configure do |config| # config.default_per_page = 25 # config.max_per_page = nil - config.window = 0 + config.window = 1 # config.outer_window = 3 - # config.left = 2 - # config.right = 2 + config.left = 2 + config.right = 2 # config.page_method_name = :page # config.param_name = :page end diff --git a/config/routes.rb b/config/routes.rb index 69134e666..b684d1382 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -84,7 +84,7 @@ RedmineApp::Application.routes.draw do resources :homework_users resources :no_uses delete 'no_uses', :to => 'no_uses#delete' - + match 'site_search', :to => 'users#site_search', :as => 'site_search', :via => [:get, :post, :put] resources :apply_project_masters delete 'apply_project_masters', :to => 'apply_project_masters#delete' @@ -457,6 +457,11 @@ RedmineApp::Application.routes.draw do end end end + resources :blog_comments do + collection do + get :search + end + end match 'users/:id/user_newfeedback', :to => 'users#user_newfeedback', :via => :get, :as => "feedback" match 'users/:id/user_projects', :to => 'users#user_projects', :via => :get #消息 diff --git a/db/schema.rb b/db/schema.rb index 8658c302b..ea8e71df6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,6 +10,7 @@ # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended to check this file into your version control system. + ActiveRecord::Schema.define(:version => 20151117075939) do create_table "activities", :force => true do |t| @@ -528,26 +529,23 @@ ActiveRecord::Schema.define(:version => 20151117075939) do add_index "documents", ["created_on"], :name => "index_documents_on_created_on" add_index "documents", ["project_id"], :name => "documents_project_id" - create_table "dts", :primary_key => "Num", :force => true do |t| - t.string "Defect", :limit => 50 - t.string "Category", :limit => 50 - t.string "File" - t.string "Method" - t.string "Module", :limit => 20 - t.string "Variable", :limit => 50 - t.integer "StartLine" - t.integer "IPLine" - t.string "IPLineCode", :limit => 200 - t.string "Judge", :limit => 15 - t.integer "Review", :limit => 1 + create_table "dts", :force => true do |t| + t.string "IPLineCode" t.string "Description" - t.text "PreConditions", :limit => 2147483647 - t.text "TraceInfo", :limit => 2147483647 - t.text "Code", :limit => 2147483647 + t.string "Num" + t.string "Variable" + t.string "TraceInfo" + t.string "Method" + t.string "File" + t.string "IPLine" + t.string "Review" + t.string "Category" + t.string "Defect" + t.string "PreConditions" + t.string "StartLine" t.integer "project_id" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "id", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "enabled_modules", :force => true do |t| @@ -572,60 +570,6 @@ ActiveRecord::Schema.define(:version => 20151117075939) do add_index "enumerations", ["id", "type"], :name => "index_enumerations_on_id_and_type" add_index "enumerations", ["project_id"], :name => "index_enumerations_on_project_id" - create_table "exercise_answers", :force => true do |t| - t.integer "user_id" - t.integer "exercise_question_id" - t.integer "exercise_choice_id" - t.text "answer_text" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "exercise_choices", :force => true do |t| - t.integer "exercise_question_id" - t.text "choice_text" - t.integer "choice_position" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "exercise_questions", :force => true do |t| - t.string "question_title" - t.integer "question_type" - t.integer "question_number" - t.integer "exercise_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "exercise_standard_answers", :force => true do |t| - t.integer "exercise_question_id" - t.integer "exercise_choice_id" - t.text "answer_text" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "exercise_users", :force => true do |t| - t.integer "user_id" - t.integer "exercise_id" - t.integer "score" - t.datetime "start_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - create_table "exercises", :force => true do |t| - t.string "exercise_name" - t.text "exercise_description" - t.integer "course_id" - t.integer "exercise_status" - t.integer "user_id" - t.integer "time" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - create_table "first_pages", :force => true do |t| t.string "web_title" t.string "title" @@ -871,6 +815,16 @@ ActiveRecord::Schema.define(:version => 20151117075939) do add_index "journal_details", ["journal_id"], :name => "journal_details_journal_id" + create_table "journal_details_copy", :force => true do |t| + t.integer "journal_id", :default => 0, :null => false + t.string "property", :limit => 30, :default => "", :null => false + t.string "prop_key", :limit => 30, :default => "", :null => false + t.text "old_value" + t.text "value" + end + + add_index "journal_details_copy", ["journal_id"], :name => "journal_details_journal_id" + create_table "journal_replies", :id => false, :force => true do |t| t.integer "journal_id" t.integer "user_id" @@ -1103,6 +1057,12 @@ ActiveRecord::Schema.define(:version => 20151117075939) do t.datetime "updated_at", :null => false end + create_table "org_courses", :force => true do |t| + t.integer "organization_id" + t.integer "course_id" + t.datetime "created_at" + end + create_table "org_document_comments", :force => true do |t| t.string "title" t.text "content" diff --git a/public/images/search_icon_03.png b/public/images/search_icon_03.png new file mode 100644 index 000000000..15ff587eb Binary files /dev/null and b/public/images/search_icon_03.png differ diff --git a/public/stylesheets/new_user.css b/public/stylesheets/new_user.css index 6ccfc47f6..753d179e7 100644 --- a/public/stylesheets/new_user.css +++ b/public/stylesheets/new_user.css @@ -1326,3 +1326,23 @@ a:hover.link_file_a{ background:url(../images/pic_file.png) 0 -25px no-repeat; c span.author { font-size: 0.9em; color: #888; } .ReplyToMessageInputContainer {width: 582px;float: left;} +/*全站搜索*/ +.blocks {padding:15px; background-color:#ffffff; border:1px solid #dddddd;} +#searchBanner {border-bottom:1px solid #d0d0d0;} +#searchBanner li {float:left; width:88px; margin-right:3px; text-align:center; padding-bottom:10px; font-weight:bold;} +#searchTips {padding:10px 5px; background-color:#f5f6f7;} +.searchBannerActive {border-bottom:3px solid #3498db !important;} +.searchBannerNormal {border-bottom:none !important;} +.searchContent {min-height:74px; border-bottom:1px solid #ededed; padding:13px 0px;} +.searchCourseware {min-height:44px; border-bottom:1px solid #ededed; padding:13px 0px; width:968px;} +.searchCourseImage {width:75px; margin-right:10px;} +.searchContentDes {width:883px;} +.searchTag {font-size:12px; color:#ffffff; background-color:#7ec8e4; height:16px; min-height:16px; max-height:16px; float:left; line-height:16px; padding:0px 3px;} +.undis {display:none;} +.dis {display:inline-block;} +.numRed {color:#FF6600;} +.pageRoll {float:right; border-left:1px solid #dddddd; margin-top:15px;} +.pageCell {border:1px solid #dddddd; padding:5px 12px; float:left; margin-left:-1px; position:relative;} +.pageCell:hover {border:1px solid #3498db; z-index:10;} +.pageCellActive {background-color:#3498db; border:1px solid #3498db !important; position:relative; color:#ffffff;} +