diff --git a/app/controllers/admins/topic/activity_forums_controller.rb b/app/controllers/admins/topic/activity_forums_controller.rb
new file mode 100644
index 000000000..b027dc003
--- /dev/null
+++ b/app/controllers/admins/topic/activity_forums_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::ActivityForumsController < Admins::Topic::BaseController
+ before_action :find_activity_forum, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::ActivityForum.ransack(title_cont: params[:search])
+ activity_forums = q.result(distinct: true)
+ @activity_forums = paginate(activity_forums)
+ end
+
+ def new
+ @activity_forum = ::Topic::ActivityForum.new
+ end
+
+ def create
+ @activity_forum = ::Topic::ActivityForum.new(activity_forum_params)
+ if @activity_forum.save
+ redirect_to admins_topic_activity_forums_path
+ flash[:success] = "新增平台动态成功"
+ else
+ redirect_to admins_topic_activity_forums_path
+ flash[:danger] = "新增平台动态失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @activity_forum.attributes = activity_forum_params
+ if @activity_forum.save
+ redirect_to admins_topic_activity_forums_path
+ flash[:success] = "更新平台动态成功"
+ else
+ redirect_to admins_topic_activity_forums_path
+ flash[:danger] = "更新平台动态失败"
+ end
+ end
+
+ def destroy
+ if @activity_forum.destroy
+ redirect_to admins_topic_activity_forums_path
+ flash[:success] = "删除平台动态成功"
+ else
+ redirect_to admins_topic_activity_forums_path
+ flash[:danger] = "删除平台动态失败"
+ end
+ end
+
+ private
+ def find_activity_forum
+ @activity_forum = ::Topic::ActivityForum.find_by_id(params[:id])
+ end
+
+ def activity_forum_params
+ params.require(:topic_activity_forum).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/banners_controller.rb b/app/controllers/admins/topic/banners_controller.rb
new file mode 100644
index 000000000..359845806
--- /dev/null
+++ b/app/controllers/admins/topic/banners_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::BannersController < Admins::Topic::BaseController
+ before_action :find_banner, only: [:edit, :update, :destroy]
+
+ def index
+ @banners = paginate(::Topic::Banner)
+ end
+
+ def new
+ @banner = ::Topic::Banner.new
+ end
+
+ def create
+ @banner = ::Topic::Banner.new(banner_params)
+ if @banner.save
+ save_image_file(params[:image], @banner)
+ redirect_to admins_topic_banners_path
+ flash[:success] = "新增banner成功"
+ else
+ redirect_to admins_topic_banners_path
+ flash[:danger] = "新增banner失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @banner.attributes = banner_params
+ if @banner.save
+ save_image_file(params[:image], @banner)
+ redirect_to admins_topic_banners_path
+ flash[:success] = "更新banner成功"
+ else
+ redirect_to admins_topic_banners_path
+ flash[:danger] = "更新banner失败"
+ end
+ end
+
+ def destroy
+ if @banner.destroy
+ redirect_to admins_topic_banners_path
+ flash[:success] = "删除banner成功"
+ else
+ redirect_to admins_topic_banners_path
+ flash[:danger] = "删除banner失败"
+ end
+ end
+
+ private
+ def find_banner
+ @banner = ::Topic::Banner.find_by_id(params[:id])
+ end
+
+ def banner_params
+ params.require(:topic_banner).permit(:title, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/base_controller.rb b/app/controllers/admins/topic/base_controller.rb
new file mode 100644
index 000000000..1360232c8
--- /dev/null
+++ b/app/controllers/admins/topic/base_controller.rb
@@ -0,0 +1,11 @@
+class Admins::Topic::BaseController < Admins::BaseController
+
+ protected
+ def save_image_file(file, topic)
+ return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
+
+ file_path = Util::FileManage.source_disk_filename(topic, 'image')
+ File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
+ Util.write_file(file, file_path)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/cards_controller.rb b/app/controllers/admins/topic/cards_controller.rb
new file mode 100644
index 000000000..732f17e5b
--- /dev/null
+++ b/app/controllers/admins/topic/cards_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::CardsController < Admins::Topic::BaseController
+ before_action :find_card, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::Card.ransack(title_cont: params[:search])
+ cards = q.result(distinct: true)
+ @cards = paginate(cards)
+ end
+
+ def new
+ @card = ::Topic::Card.new
+ end
+
+ def create
+ @card = ::Topic::Card.new(card_params)
+ if @card.save
+ redirect_to admins_topic_cards_path
+ flash[:success] = "新增合作单位成功"
+ else
+ redirect_to admins_topic_cards_path
+ flash[:danger] = "新增合作单位失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @card.attributes = card_params
+ if @card.save
+ redirect_to admins_topic_cards_path
+ flash[:success] = "更新合作单位成功"
+ else
+ redirect_to admins_topic_cards_path
+ flash[:danger] = "更新合作单位失败"
+ end
+ end
+
+ def destroy
+ if @card.destroy
+ redirect_to admins_topic_cards_path
+ flash[:success] = "删除合作单位成功"
+ else
+ redirect_to admins_topic_cards_path
+ flash[:danger] = "删除合作单位失败"
+ end
+ end
+
+ private
+ def find_card
+ @card = ::Topic::Card.find_by_id(params[:id])
+ end
+
+ def card_params
+ params.require(:topic_card).permit(:title, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/cooperators_controller.rb b/app/controllers/admins/topic/cooperators_controller.rb
new file mode 100644
index 000000000..a1a700cbc
--- /dev/null
+++ b/app/controllers/admins/topic/cooperators_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::CooperatorsController < Admins::Topic::BaseController
+ before_action :find_cooperator, only: [:edit, :update, :destroy]
+
+ def index
+ @cooperators = paginate(::Topic::Cooperator)
+ end
+
+ def new
+ @cooperator = ::Topic::Cooperator.new
+ end
+
+ def create
+ @cooperator = ::Topic::Cooperator.new(cooperator_params)
+ if @cooperator.save
+ save_image_file(params[:image], @cooperator)
+ redirect_to admins_topic_cooperators_path
+ flash[:success] = "新增合作单位成功"
+ else
+ redirect_to admins_topic_cooperators_path
+ flash[:danger] = "新增合作单位失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @cooperator.attributes = cooperator_params
+ if @cooperator.save
+ save_image_file(params[:image], @cooperator)
+ redirect_to admins_topic_cooperators_path
+ flash[:success] = "更新合作单位成功"
+ else
+ redirect_to admins_topic_cooperators_path
+ flash[:danger] = "更新合作单位失败"
+ end
+ end
+
+ def destroy
+ if @cooperator.destroy
+ redirect_to admins_topic_cooperators_path
+ flash[:success] = "删除合作单位成功"
+ else
+ redirect_to admins_topic_cooperators_path
+ flash[:danger] = "删除合作单位失败"
+ end
+ end
+
+ private
+ def find_cooperator
+ @cooperator = ::Topic::Cooperator.find_by_id(params[:id])
+ end
+
+ def cooperator_params
+ params.require(:topic_cooperator).permit(:title, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/excellent_projects_controller.rb b/app/controllers/admins/topic/excellent_projects_controller.rb
new file mode 100644
index 000000000..b60dac54c
--- /dev/null
+++ b/app/controllers/admins/topic/excellent_projects_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::ExcellentProjectsController < Admins::Topic::BaseController
+ before_action :find_excellent_project, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::ExcellentProject.ransack(title_cont: params[:search])
+ excellent_projects = q.result(distinct: true)
+ @excellent_projects = paginate(excellent_projects)
+ end
+
+ def new
+ @excellent_project = ::Topic::ExcellentProject.new
+ end
+
+ def create
+ @excellent_project = ::Topic::ExcellentProject.new(excellent_project_params)
+ if @excellent_project.save
+ redirect_to admins_topic_excellent_projects_path
+ flash[:success] = "新增优秀仓库成功"
+ else
+ redirect_to admins_topic_excellent_projects_path
+ flash[:danger] = "新增优秀仓库失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @excellent_project.attributes = excellent_project_params
+ if @excellent_project.save
+ redirect_to admins_topic_excellent_projects_path
+ flash[:success] = "更新优秀仓库成功"
+ else
+ redirect_to admins_topic_excellent_projects_path
+ flash[:danger] = "更新优秀仓库失败"
+ end
+ end
+
+ def destroy
+ if @excellent_project.destroy
+ redirect_to admins_topic_excellent_projects_path
+ flash[:success] = "删除优秀仓库成功"
+ else
+ redirect_to admins_topic_excellent_projects_path
+ flash[:danger] = "删除优秀仓库失败"
+ end
+ end
+
+ private
+ def find_excellent_project
+ @excellent_project = ::Topic::ExcellentProject.find_by_id(params[:id])
+ end
+
+ def excellent_project_params
+ params.require(:topic_excellent_project).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/experience_forums_controller.rb b/app/controllers/admins/topic/experience_forums_controller.rb
new file mode 100644
index 000000000..420670c1b
--- /dev/null
+++ b/app/controllers/admins/topic/experience_forums_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::ExperienceForumsController < Admins::Topic::BaseController
+ before_action :find_experience_forum, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::ExperienceForum.ransack(title_cont: params[:search])
+ experience_forums = q.result(distinct: true)
+ @experience_forums = paginate(experience_forums)
+ end
+
+ def new
+ @experience_forum = ::Topic::ExperienceForum.new
+ end
+
+ def create
+ @experience_forum = ::Topic::ExperienceForum.new(experience_forum_params)
+ if @experience_forum.save
+ redirect_to admins_topic_experience_forums_path
+ flash[:success] = "新增经验分享成功"
+ else
+ redirect_to admins_topic_experience_forums_path
+ flash[:danger] = "新增经验分享失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @experience_forum.attributes = experience_forum_params
+ if @experience_forum.save
+ redirect_to admins_topic_experience_forums_path
+ flash[:success] = "更新经验分享成功"
+ else
+ redirect_to admins_topic_experience_forums_path
+ flash[:danger] = "更新经验分享失败"
+ end
+ end
+
+ def destroy
+ if @experience_forum.destroy
+ redirect_to admins_topic_experience_forums_path
+ flash[:success] = "删除经验分享成功"
+ else
+ redirect_to admins_topic_experience_forums_path
+ flash[:danger] = "删除经验分享失败"
+ end
+ end
+
+ private
+ def find_experience_forum
+ @experience_forum = ::Topic::ExperienceForum.find_by_id(params[:id])
+ end
+
+ def experience_forum_params
+ params.require(:topic_experience_forum).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/pinned_forums_controller.rb b/app/controllers/admins/topic/pinned_forums_controller.rb
new file mode 100644
index 000000000..ac5bf69a7
--- /dev/null
+++ b/app/controllers/admins/topic/pinned_forums_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::PinnedForumsController < Admins::Topic::BaseController
+ before_action :find_pinned_forum, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::PinnedForum.ransack(title_cont: params[:search])
+ pinned_forums = q.result(distinct: true)
+ @pinned_forums = paginate(pinned_forums)
+ end
+
+ def new
+ @pinned_forum = ::Topic::PinnedForum.new
+ end
+
+ def create
+ @pinned_forum = ::Topic::PinnedForum.new(pinned_forum_params)
+ if @pinned_forum.save
+ redirect_to admins_topic_pinned_forums_path
+ flash[:success] = "新增精选文章成功"
+ else
+ redirect_to admins_topic_pinned_forums_path
+ flash[:danger] = "新增精选文章失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @pinned_forum.attributes = pinned_forum_params
+ if @pinned_forum.save
+ redirect_to admins_topic_pinned_forums_path
+ flash[:success] = "更新精选文章成功"
+ else
+ redirect_to admins_topic_pinned_forums_path
+ flash[:danger] = "更新精选文章失败"
+ end
+ end
+
+ def destroy
+ if @pinned_forum.destroy
+ redirect_to admins_topic_pinned_forums_path
+ flash[:success] = "删除精选文章成功"
+ else
+ redirect_to admins_topic_pinned_forums_path
+ flash[:danger] = "删除精选文章失败"
+ end
+ end
+
+ private
+ def find_pinned_forum
+ @pinned_forum = ::Topic::PinnedForum.find_by_id(params[:id])
+ end
+
+ def pinned_forum_params
+ params.require(:topic_pinned_forum).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1aff1c09a..30bcb56c7 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -609,7 +609,7 @@ class ApplicationController < ActionController::Base
def kaminari_paginate(relation)
limit = params[:limit] || params[:per_page]
- limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
+ limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
@@ -617,7 +617,7 @@ class ApplicationController < ActionController::Base
def kaminari_array_paginate(relation)
limit = params[:limit] || params[:per_page]
- limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
+ limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
Kaminari.paginate_array(relation).page(page).per(limit)
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
new file mode 100644
index 000000000..207b45870
--- /dev/null
+++ b/app/controllers/topics_controller.rb
@@ -0,0 +1,9 @@
+class TopicsController < ApplicationController
+
+ def index
+ return render_not_found("请输入正确的数据类型") unless params[:topic_type].present?
+ scope = Topic.with_single_type(params[:topic_type])
+ @topics = kaminari_paginate(scope)
+ end
+
+end
\ No newline at end of file
diff --git a/app/libs/forum.rb b/app/libs/forum.rb
new file mode 100644
index 000000000..112ff2788
--- /dev/null
+++ b/app/libs/forum.rb
@@ -0,0 +1,20 @@
+module Forum
+ class << self
+ def forum_config
+ forum_config = {}
+
+ begin
+ config = Rails.application.config_for(:configuration).symbolize_keys!
+ forum_config = config[:forum].symbolize_keys!
+ raise 'forum config missing' if forum_config.blank?
+ rescue => ex
+ raise ex if Rails.env.production?
+
+ puts %Q{\033[33m [warning] forum config or configuration.yml missing,
+ please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
+ forum_config = {}
+ end
+ forum_config
+ end
+ end
+end
diff --git a/app/models/topic.rb b/app/models/topic.rb
new file mode 100644
index 000000000..13bf7b5bd
--- /dev/null
+++ b/app/models/topic.rb
@@ -0,0 +1,50 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+class Topic < ApplicationRecord
+
+ default_scope { order(order_index: :desc)}
+
+ scope :with_single_type, ->(type){where(type: trans_simpletype_to_classtype(type))}
+
+ def image
+ image_url('image')
+ end
+
+ def self.trans_simpletype_to_classtype(type)
+ case type
+ when 'activity_forum'
+ 'Topic::ActivityForum'
+ when 'banner'
+ 'Topic::Banner'
+ when 'card'
+ 'Topic::Card'
+ when 'cooperator'
+ 'Topic::Cooperator'
+ when 'excellent_project'
+ 'Topic::ExcellentProject'
+ when 'experience_forum'
+ 'Topic::ExperienceForum'
+ when 'pinned_forum'
+ 'Topic::PinnedForum'
+ end
+ end
+
+ private
+
+ def image_url(type)
+ return nil unless Util::FileManage.exists?(self, type)
+ Util::FileManage.source_disk_file_url(self, type)
+ end
+
+end
diff --git a/app/models/topic/activity_forum.rb b/app/models/topic/activity_forum.rb
new file mode 100644
index 000000000..8cf9adf83
--- /dev/null
+++ b/app/models/topic/activity_forum.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页平台动态
+class Topic::ActivityForum < Topic
+
+end
diff --git a/app/models/topic/banner.rb b/app/models/topic/banner.rb
new file mode 100644
index 000000000..e5b77bec0
--- /dev/null
+++ b/app/models/topic/banner.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页banner
+class Topic::Banner < Topic
+end
diff --git a/app/models/topic/card.rb b/app/models/topic/card.rb
new file mode 100644
index 000000000..6a54e17ea
--- /dev/null
+++ b/app/models/topic/card.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页卡片内容
+class Topic::Card < Topic
+end
diff --git a/app/models/topic/cooperator.rb b/app/models/topic/cooperator.rb
new file mode 100644
index 000000000..a023d3656
--- /dev/null
+++ b/app/models/topic/cooperator.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页合作伙伴
+class Topic::Cooperator < Topic
+end
diff --git a/app/models/topic/excellent_project.rb b/app/models/topic/excellent_project.rb
new file mode 100644
index 000000000..ac08863c7
--- /dev/null
+++ b/app/models/topic/excellent_project.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页优秀项目
+class Topic::ExcellentProject < Topic
+
+end
diff --git a/app/models/topic/experience_forum.rb b/app/models/topic/experience_forum.rb
new file mode 100644
index 000000000..855a56809
--- /dev/null
+++ b/app/models/topic/experience_forum.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页经验分享
+class Topic::ExperienceForum < Topic
+end
diff --git a/app/models/topic/pinned_forum.rb b/app/models/topic/pinned_forum.rb
new file mode 100644
index 000000000..c5a2c8572
--- /dev/null
+++ b/app/models/topic/pinned_forum.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页精选文章
+class Topic::PinnedForum < Topic
+end
diff --git a/app/services/forum/client_service.rb b/app/services/forum/client_service.rb
new file mode 100644
index 000000000..e3ff54691
--- /dev/null
+++ b/app/services/forum/client_service.rb
@@ -0,0 +1,94 @@
+class Forum::ClientService < ApplicationService
+ attr_reader :url, :params
+
+ PAGINATE_DEFAULT_PAGE = 1
+ PAGINATE_DEFAULT_LIMIT = 20
+
+ def initialize(options={})
+ @url = options[:url]
+ @params = options[:params]
+ end
+
+ def get(url, params={})
+ conn(params).get do |req|
+ req.url full_url(url, 'get')
+ params.except(:token).each_pair do |key, value|
+ req.params["#{key}"] = value
+ end
+ end
+
+ # response.headers.each do |k,v|
+ # puts "#{k}:#{v}"
+ # end #=> 响应头
+ end
+
+ private
+ def conn(auth={})
+ @client ||= begin
+ Faraday.new(url: domain) do |req|
+ req.request :url_encoded
+ req.headers['Content-Type'] = 'application/json'
+ req.response :logger # 显示日志
+ req.adapter Faraday.default_adapter
+ end
+ end
+ @client
+ end
+
+ def base_url
+ Forum.forum_config[:base_url]
+ end
+
+ def domain
+ Forum.forum_config[:domain]
+ end
+
+ def api_url
+ [domain, base_url].join('')
+ end
+
+ def full_url(api_rest, action='post')
+ url = [api_url, api_rest].join('').freeze
+ url = action === 'get' ? url : URI.escape(url)
+ url = URI.escape(url) unless url.ascii_only?
+ puts "[forum] request url: #{url}"
+ return url
+ end
+
+ def render_response(response)
+ status = response.status
+ body = response&.body
+
+ # log_error(status, body)
+
+ body, message = get_body_by_status(status, body)
+
+ [status, message, body]
+ end
+
+ def get_body_by_status(status, body)
+ body, message =
+ case status
+ when 401 then [nil, "401"]
+ when 404 then [nil, "404"]
+ when 403 then [nil, "403"]
+ when 500 then [nil, "500"]
+ else
+ if body.present?
+ body = JSON.parse(body)
+ fix_body(body)
+ else
+ nil
+ end
+ end
+
+ [body, message]
+ end
+
+ def fix_body(body)
+ return [body, nil] if body.is_a?(Array) || body.is_a?(Hash)
+
+ body['message'].blank? ? [body, nil] : [nil, body['message']]
+ end
+
+end
diff --git a/app/services/forum/memos/get_service.rb b/app/services/forum/memos/get_service.rb
new file mode 100644
index 000000000..c8ad56895
--- /dev/null
+++ b/app/services/forum/memos/get_service.rb
@@ -0,0 +1,21 @@
+class Forum::Memos::GetService < Forum::ClientService
+ attr_reader :memo_id
+
+ def initialize(memo_id)
+ @memo_id = memo_id
+ end
+
+ def call
+ response = get(url)
+ code, message, body = render_response(response)
+ if code == 200 && body["status"] == 0
+ return body
+ else
+ return nil
+ end
+ end
+
+ def url
+ "/memos/#{memo_id}.json".freeze
+ end
+end
\ No newline at end of file
diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb
index 75abbc124..0b88ddc0b 100644
--- a/app/views/admins/shared/_sidebar.html.erb
+++ b/app/views/admins/shared/_sidebar.html.erb
@@ -31,7 +31,17 @@
<%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %>
<%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %>
-
+
+ <%= sidebar_item_group('#setting-index', '首页配置', icon: 'file') do %>
+ <%= sidebar_item(admins_topic_banners_path, 'banner管理', icon: 'image', controller: 'admins-topic-banners') %>
+ <%= sidebar_item(admins_topic_cards_path, '卡片管理', icon: 'archive', controller: 'admins-topic-cards') %>
+ <%= sidebar_item(admins_topic_activity_forums_path, '平台动态管理', icon: 'bell', controller: 'admins-topic-activity_forums') %>
+ <%= sidebar_item(admins_topic_excellent_projects_path, '优秀仓库管理', icon: 'git', controller: 'admins-topic-excellent_projects') %>
+ <%= sidebar_item(admins_topic_pinned_forums_path, '精选文章管理', icon: 'edit', controller: 'admins-topic-pinned_forums') %>
+ <%= sidebar_item(admins_topic_experience_forums_path, '经验分享管理', icon: 'edit', controller: 'admins-topic-experience_forums') %>
+ <%= sidebar_item(admins_topic_cooperators_path, '合作伙伴管理', icon: 'user', controller: 'admins-topic-cooperators') %>
+ <% end %>
+
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
<%= sidebar_item(edit_admins_about_path, '关于我们', icon: 'smile-o', controller: 'admins-abouts') %>
diff --git a/app/views/admins/topic/activity_forums/_form_modal.html.erb b/app/views/admins/topic/activity_forums/_form_modal.html.erb
new file mode 100644
index 000000000..3426337d2
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @activity_forum, url: {controller: "topic/activity_forums", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 帖子ID *
+
+ <%= p.text_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/_list.html.erb b/app/views/admins/topic/activity_forums/_list.html.erb
new file mode 100644
index 000000000..35068eddb
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 帖子ID
+ 排序等级
+ 操作
+
+
+
+ <% if activity_forums.present? %>
+ <% activity_forums.each_with_index do |activity_forum, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= activity_forum.title %>
+ <%= activity_forum.url %>
+ <%= activity_forum.uuid %>
+ <%= activity_forum.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_activity_forum_path(activity_forum), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_activity_forum_path(activity_forum), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: activity_forums } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/edit.js.erb b/app/views/admins/topic/activity_forums/edit.js.erb
new file mode 100644
index 000000000..b66ecd1c4
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/edit.js.erb
@@ -0,0 +1,2 @@
+$("#activity-forum-modals").html("<%= j render(partial: 'admins/topic/activity_forums/form_modal', locals: {type: 'update'}) %>")
+$(".activity-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/index.html.erb b/app/views/admins/topic/activity_forums/index.html.erb
new file mode 100644
index 000000000..a6d673d31
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('平台动态管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_activity_forums_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_activity_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/activity_forums/list', locals: { activity_forums: @activity_forums } %>
+
+
+
diff --git a/app/views/admins/topic/activity_forums/index.js.erb b/app/views/admins/topic/activity_forums/index.js.erb
new file mode 100644
index 000000000..3560c21f1
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/index.js.erb
@@ -0,0 +1 @@
+$('.activity-forum-list-container').html("<%= j( render partial: 'admins/topic/activity_forums/list', locals: { activity_forums: @activity_forums } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/new.js.erb b/app/views/admins/topic/activity_forums/new.js.erb
new file mode 100644
index 000000000..8e9a33097
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/new.js.erb
@@ -0,0 +1,2 @@
+$("#activity-forum-modals").html("<%= j render(partial: 'admins/topic/activity_forums/form_modal', locals: {type: 'create'}) %>")
+$(".activity-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/_form_modal.html.erb b/app/views/admins/topic/banners/_form_modal.html.erb
new file mode 100644
index 000000000..20bca80c6
--- /dev/null
+++ b/app/views/admins/topic/banners/_form_modal.html.erb
@@ -0,0 +1,45 @@
+
+
+
+
+ <%= form_for @banner, url: {controller: "topic/banners", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+ <% logo_img = @banner.image %>
+
+
+ <%= file_field_tag(:image, accept: 'image/png,image/jpg,image/jpeg',style: "display: none", value: params[:image]) %>
+
+
+
+
logo
+
格式:PNG、JPG
+
尺寸:高度38px以内,宽等比例缩放
+
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/_list.html.erb b/app/views/admins/topic/banners/_list.html.erb
new file mode 100644
index 000000000..aa366ec21
--- /dev/null
+++ b/app/views/admins/topic/banners/_list.html.erb
@@ -0,0 +1,31 @@
+
+
+
+ 序号
+ 标题
+ 图片
+ 排序等级
+ 操作
+
+
+
+ <% if banners.present? %>
+ <% banners.each_with_index do |banner, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= banner.title %>
+
+ <%= banner.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_banner_path(banner), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_banner_path(banner), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: banners } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/edit.js.erb b/app/views/admins/topic/banners/edit.js.erb
new file mode 100644
index 000000000..524bb13a7
--- /dev/null
+++ b/app/views/admins/topic/banners/edit.js.erb
@@ -0,0 +1,18 @@
+$("#banner-modals").html("<%= j render(partial: 'admins/topic/banners/form_modal', locals: {type: 'update'}) %>")
+$(".banner-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/banners/index.html.erb b/app/views/admins/topic/banners/index.html.erb
new file mode 100644
index 000000000..e8ceefa2f
--- /dev/null
+++ b/app/views/admins/topic/banners/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('卡片管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_banners_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_banner_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/banners/list', locals: { banners: @banners } %>
+
+
+
diff --git a/app/views/admins/topic/banners/index.js.erb b/app/views/admins/topic/banners/index.js.erb
new file mode 100644
index 000000000..0095bd861
--- /dev/null
+++ b/app/views/admins/topic/banners/index.js.erb
@@ -0,0 +1 @@
+$('.banner-list-container').html("<%= j( render partial: 'admins/topic/banners/list', locals: { banners: @banners } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/new.js.erb b/app/views/admins/topic/banners/new.js.erb
new file mode 100644
index 000000000..d1450eb7f
--- /dev/null
+++ b/app/views/admins/topic/banners/new.js.erb
@@ -0,0 +1,18 @@
+$("#banner-modals").html("<%= j render(partial: 'admins/topic/banners/form_modal', locals: {type: 'create'}) %>")
+$(".banner-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/cards/_form_modal.html.erb b/app/views/admins/topic/cards/_form_modal.html.erb
new file mode 100644
index 000000000..960b8b503
--- /dev/null
+++ b/app/views/admins/topic/cards/_form_modal.html.erb
@@ -0,0 +1,38 @@
+
+
+
+
+ <%= form_for @card, url: {controller: "topic/cards", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/_list.html.erb b/app/views/admins/topic/cards/_list.html.erb
new file mode 100644
index 000000000..71a460199
--- /dev/null
+++ b/app/views/admins/topic/cards/_list.html.erb
@@ -0,0 +1,31 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 排序等级
+ 操作
+
+
+
+ <% if cards.present? %>
+ <% cards.each_with_index do |card, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= card.title %>
+ <%= card.url %>
+ <%= card.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_card_path(card), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_card_path(card), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: cards } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/edit.js.erb b/app/views/admins/topic/cards/edit.js.erb
new file mode 100644
index 000000000..9d0ed0e74
--- /dev/null
+++ b/app/views/admins/topic/cards/edit.js.erb
@@ -0,0 +1,2 @@
+$("#card-modals").html("<%= j render(partial: 'admins/topic/cards/form_modal', locals: {type: 'update'}) %>")
+$(".card-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/index.html.erb b/app/views/admins/topic/cards/index.html.erb
new file mode 100644
index 000000000..6865fa107
--- /dev/null
+++ b/app/views/admins/topic/cards/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('卡片管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_cards_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_card_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/cards/list', locals: { cards: @cards } %>
+
+
+
diff --git a/app/views/admins/topic/cards/index.js.erb b/app/views/admins/topic/cards/index.js.erb
new file mode 100644
index 000000000..1bbcb5487
--- /dev/null
+++ b/app/views/admins/topic/cards/index.js.erb
@@ -0,0 +1 @@
+$('.card-list-container').html("<%= j( render partial: 'admins/topic/cards/list', locals: { cards: @cards } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/new.js.erb b/app/views/admins/topic/cards/new.js.erb
new file mode 100644
index 000000000..94b8353b9
--- /dev/null
+++ b/app/views/admins/topic/cards/new.js.erb
@@ -0,0 +1,2 @@
+$("#card-modals").html("<%= j render(partial: 'admins/topic/cards/form_modal', locals: {type: 'create'}) %>")
+$(".card-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/_form_modal.html.erb b/app/views/admins/topic/cooperators/_form_modal.html.erb
new file mode 100644
index 000000000..8f9085292
--- /dev/null
+++ b/app/views/admins/topic/cooperators/_form_modal.html.erb
@@ -0,0 +1,51 @@
+
+
+
+
+ <%= form_for @cooperator, url: {controller: "topic/cooperators", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+ <% logo_img = @cooperator.image %>
+
+
+ <%= file_field_tag(:image, accept: 'image/png,image/jpg,image/jpeg',style: "display: none", value: params[:image]) %>
+
+
+
+
logo
+
格式:PNG、JPG
+
尺寸:高度38px以内,宽等比例缩放
+
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/_list.html.erb b/app/views/admins/topic/cooperators/_list.html.erb
new file mode 100644
index 000000000..351b6b9de
--- /dev/null
+++ b/app/views/admins/topic/cooperators/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 图片
+ 排序等级
+ 操作
+
+
+
+ <% if cooperators.present? %>
+ <% cooperators.each_with_index do |cooperator, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= cooperator.title %>
+ <%= cooperator.url %>
+
+ <%= cooperator.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_cooperator_path(cooperator), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_cooperator_path(cooperator), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: cooperators } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/edit.js.erb b/app/views/admins/topic/cooperators/edit.js.erb
new file mode 100644
index 000000000..ec99bfcef
--- /dev/null
+++ b/app/views/admins/topic/cooperators/edit.js.erb
@@ -0,0 +1,18 @@
+$("#cooperator-modals").html("<%= j render(partial: 'admins/topic/cooperators/form_modal', locals: {type: 'update'}) %>")
+$(".cooperator-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/cooperators/index.html.erb b/app/views/admins/topic/cooperators/index.html.erb
new file mode 100644
index 000000000..e18bc397f
--- /dev/null
+++ b/app/views/admins/topic/cooperators/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('卡片管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_cooperators_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_cooperator_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/cooperators/list', locals: { cooperators: @cooperators } %>
+
+
+
diff --git a/app/views/admins/topic/cooperators/index.js.erb b/app/views/admins/topic/cooperators/index.js.erb
new file mode 100644
index 000000000..e3bbc044b
--- /dev/null
+++ b/app/views/admins/topic/cooperators/index.js.erb
@@ -0,0 +1 @@
+$('.cooperator-list-container').html("<%= j( render partial: 'admins/topic/cooperators/list', locals: { cooperators: @cooperators } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/new.js.erb b/app/views/admins/topic/cooperators/new.js.erb
new file mode 100644
index 000000000..d986f4e7d
--- /dev/null
+++ b/app/views/admins/topic/cooperators/new.js.erb
@@ -0,0 +1,18 @@
+$("#cooperator-modals").html("<%= j render(partial: 'admins/topic/cooperators/form_modal', locals: {type: 'create'}) %>")
+$(".cooperator-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/excellent_projects/_form_modal.html.erb b/app/views/admins/topic/excellent_projects/_form_modal.html.erb
new file mode 100644
index 000000000..4e48063b8
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @excellent_project, url: {controller: "topic/excellent_projects", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 项目ID *
+
+ <%= p.number_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/_list.html.erb b/app/views/admins/topic/excellent_projects/_list.html.erb
new file mode 100644
index 000000000..7642037db
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 项目ID
+ 排序等级
+ 操作
+
+
+
+ <% if excellent_projects.present? %>
+ <% excellent_projects.each_with_index do |excellent_project, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= excellent_project.title %>
+ <%= excellent_project.url %>
+ <%= excellent_project.uuid %>
+ <%= excellent_project.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_excellent_project_path(excellent_project), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_excellent_project_path(excellent_project), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: excellent_projects } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/edit.js.erb b/app/views/admins/topic/excellent_projects/edit.js.erb
new file mode 100644
index 000000000..d47b1a92a
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/edit.js.erb
@@ -0,0 +1,2 @@
+$("#excellent-project-modals").html("<%= j render(partial: 'admins/topic/excellent_projects/form_modal', locals: {type: 'update'}) %>")
+$(".excellent-project-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/index.html.erb b/app/views/admins/topic/excellent_projects/index.html.erb
new file mode 100644
index 000000000..1b529344b
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('优秀仓库管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_excellent_projects_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_excellent_project_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/excellent_projects/list', locals: { excellent_projects: @excellent_projects } %>
+
+
+
diff --git a/app/views/admins/topic/excellent_projects/index.js.erb b/app/views/admins/topic/excellent_projects/index.js.erb
new file mode 100644
index 000000000..969abd1e0
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/index.js.erb
@@ -0,0 +1 @@
+$('.excellent-project-list-container').html("<%= j( render partial: 'admins/topic/excellent_projects/list', locals: { excellent_projects: @excellent_projects } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/new.js.erb b/app/views/admins/topic/excellent_projects/new.js.erb
new file mode 100644
index 000000000..1b7e13095
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/new.js.erb
@@ -0,0 +1,2 @@
+$("#excellent-project-modals").html("<%= j render(partial: 'admins/topic/excellent_projects/form_modal', locals: {type: 'create'}) %>")
+$(".excellent-project-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/_form_modal.html.erb b/app/views/admins/topic/experience_forums/_form_modal.html.erb
new file mode 100644
index 000000000..971b8ca51
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @experience_forum, url: {controller: "topic/experience_forums", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 帖子ID *
+
+ <%= p.number_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/_list.html.erb b/app/views/admins/topic/experience_forums/_list.html.erb
new file mode 100644
index 000000000..b6f5e91fc
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 帖子ID
+ 排序等级
+ 操作
+
+
+
+ <% if experience_forums.present? %>
+ <% experience_forums.each_with_index do |experience_forum, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= experience_forum.title %>
+ <%= experience_forum.url %>
+ <%= experience_forum.uuid %>
+ <%= experience_forum.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_experience_forum_path(experience_forum), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_experience_forum_path(experience_forum), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: experience_forums } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/edit.js.erb b/app/views/admins/topic/experience_forums/edit.js.erb
new file mode 100644
index 000000000..5684a1b1f
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/edit.js.erb
@@ -0,0 +1,2 @@
+$("#experience-forum-modals").html("<%= j render(partial: 'admins/topic/experience_forums/form_modal', locals: {type: 'update'}) %>")
+$(".experience-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/index.html.erb b/app/views/admins/topic/experience_forums/index.html.erb
new file mode 100644
index 000000000..e66738762
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('经验分享管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_experience_forums_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_experience_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/experience_forums/list', locals: { experience_forums: @experience_forums } %>
+
+
+
diff --git a/app/views/admins/topic/experience_forums/index.js.erb b/app/views/admins/topic/experience_forums/index.js.erb
new file mode 100644
index 000000000..9653cd9a8
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/index.js.erb
@@ -0,0 +1 @@
+$('.experience-forum-list-container').html("<%= j( render partial: 'admins/topic/experience_forums/list', locals: { experience_forums: @experience_forums } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/new.js.erb b/app/views/admins/topic/experience_forums/new.js.erb
new file mode 100644
index 000000000..5020e9ed1
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/new.js.erb
@@ -0,0 +1,2 @@
+$("#experience-forum-modals").html("<%= j render(partial: 'admins/topic/experience_forums/form_modal', locals: {type: 'create'}) %>")
+$(".experience-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/_form_modal.html.erb b/app/views/admins/topic/pinned_forums/_form_modal.html.erb
new file mode 100644
index 000000000..45c6eb8ec
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @pinned_forum, url: {controller: "topic/pinned_forums", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 帖子ID *
+
+ <%= p.number_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/_list.html.erb b/app/views/admins/topic/pinned_forums/_list.html.erb
new file mode 100644
index 000000000..9169b6a20
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 帖子ID
+ 排序等级
+ 操作
+
+
+
+ <% if pinned_forums.present? %>
+ <% pinned_forums.each_with_index do |pinned_forum, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= pinned_forum.title %>
+ <%= pinned_forum.url %>
+ <%= pinned_forum.uuid %>
+ <%= pinned_forum.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_pinned_forum_path(pinned_forum), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_pinned_forum_path(pinned_forum), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: pinned_forums } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/edit.js.erb b/app/views/admins/topic/pinned_forums/edit.js.erb
new file mode 100644
index 000000000..77875c679
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/edit.js.erb
@@ -0,0 +1,2 @@
+$("#pinned-forum-modals").html("<%= j render(partial: 'admins/topic/pinned_forums/form_modal', locals: {type: 'update'}) %>")
+$(".pinned-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/index.html.erb b/app/views/admins/topic/pinned_forums/index.html.erb
new file mode 100644
index 000000000..d6cf788b6
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('精选文章管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_pinned_forums_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_pinned_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/pinned_forums/list', locals: { pinned_forums: @pinned_forums } %>
+
+
+
diff --git a/app/views/admins/topic/pinned_forums/index.js.erb b/app/views/admins/topic/pinned_forums/index.js.erb
new file mode 100644
index 000000000..78d1a240a
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/index.js.erb
@@ -0,0 +1 @@
+$('.pinned-forum-list-container').html("<%= j( render partial: 'admins/topic/pinned_forums/list', locals: { pinned_forums: @pinned_forums } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/new.js.erb b/app/views/admins/topic/pinned_forums/new.js.erb
new file mode 100644
index 000000000..1069707c0
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/new.js.erb
@@ -0,0 +1,2 @@
+$("#pinned-forum-modals").html("<%= j render(partial: 'admins/topic/pinned_forums/form_modal', locals: {type: 'create'}) %>")
+$(".pinned-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/topics/_activity_forum.json.jbuilder b/app/views/topics/_activity_forum.json.jbuilder
new file mode 100644
index 000000000..cd624ba76
--- /dev/null
+++ b/app/views/topics/_activity_forum.json.jbuilder
@@ -0,0 +1,4 @@
+json.(activity_forum, :id, :title, :url)
+request_memo = Forum::Memos::GetService.call(activity_forum&.uuid)
+json.visits request_memo.nil? ? 0 : request_memo["memo"]["viewed_count"]
+json.created_time request_memo.nil? ? format_time(Time.now) : request_memo["memo"]["published_time"]
\ No newline at end of file
diff --git a/app/views/topics/_banner.json.jbuilder b/app/views/topics/_banner.json.jbuilder
new file mode 100644
index 000000000..01fa7c9a2
--- /dev/null
+++ b/app/views/topics/_banner.json.jbuilder
@@ -0,0 +1 @@
+json.(banner, :id, :title, :image)
\ No newline at end of file
diff --git a/app/views/topics/_card.json.jbuilder b/app/views/topics/_card.json.jbuilder
new file mode 100644
index 000000000..9f4617a3a
--- /dev/null
+++ b/app/views/topics/_card.json.jbuilder
@@ -0,0 +1 @@
+json.(card, :id, :title, :url)
\ No newline at end of file
diff --git a/app/views/topics/_cooperator.json.jbuilder b/app/views/topics/_cooperator.json.jbuilder
new file mode 100644
index 000000000..ef4fc5b9a
--- /dev/null
+++ b/app/views/topics/_cooperator.json.jbuilder
@@ -0,0 +1 @@
+json.(cooperator, :id, :title, :image, :url)
diff --git a/app/views/topics/_excellent_project.json.jbuilder b/app/views/topics/_excellent_project.json.jbuilder
new file mode 100644
index 000000000..341694add
--- /dev/null
+++ b/app/views/topics/_excellent_project.json.jbuilder
@@ -0,0 +1,3 @@
+json.(excellent_project, :id, :title, :url)
+project_common = $redis_cache.hgetall("v2-project-common:#{excellent_project&.uuid}")
+json.visits (project_common['visits'] || 0).to_i
diff --git a/app/views/topics/_experience_forum.json.jbuilder b/app/views/topics/_experience_forum.json.jbuilder
new file mode 100644
index 000000000..c65a00ef8
--- /dev/null
+++ b/app/views/topics/_experience_forum.json.jbuilder
@@ -0,0 +1,4 @@
+json.(experience_forum, :id, :title, :url)
+request_memo = Forum::Memos::GetService.call(experience_forum&.uuid)
+json.visits request_memo.nil? ? 0 : request_memo["memo"]["viewed_count"]
+json.created_time request_memo.nil? ? format_time(Time.now) : request_memo["memo"]["published_time"]
\ No newline at end of file
diff --git a/app/views/topics/_pinned_forum.json.jbuilder b/app/views/topics/_pinned_forum.json.jbuilder
new file mode 100644
index 000000000..3d5adce26
--- /dev/null
+++ b/app/views/topics/_pinned_forum.json.jbuilder
@@ -0,0 +1,4 @@
+json.(pinned_forum, :id, :title, :url)
+request_memo = Forum::Memos::GetService.call(pinned_forum&.uuid)
+json.visits request_memo.nil? ? 0 : request_memo["memo"]["viewed_count"]
+json.created_time request_memo.nil? ? format_time(Time.now) : request_memo["memo"]["published_time"]
\ No newline at end of file
diff --git a/app/views/topics/index.json.jbuilder b/app/views/topics/index.json.jbuilder
new file mode 100644
index 000000000..102da6b11
--- /dev/null
+++ b/app/views/topics/index.json.jbuilder
@@ -0,0 +1,49 @@
+json.partial! "commons/success"
+json.total_count @topics.total_count
+json.topics do
+ if params[:group_size].present?
+ json.array! @topics.to_a.each_slice(params[:group_size].to_i).to_a.each do |group|
+ json.array! group.each do |topic|
+ case topic.type
+ when "Topic::ActivityForum"
+ json.partial! "activity_forum", locals: {activity_forum: topic}
+ when "Topic::Banner"
+ json.partial! "banner", locals: {banner: topic}
+ when "Topic::Card"
+ json.partial! "card", locals: {card: topic}
+ when "Topic::Cooperator"
+ json.partial! "cooperator", locals: {cooperator: topic}
+ when "Topic::ExcellentProject"
+ json.partial! "excellent_project", locals: {excellent_project: topic}
+ when "Topic::ExperienceForum"
+ json.partial! "experience_forum", locals: {experience_forum: topic}
+ when "Topic::PinnedForum"
+ json.partial! "pinned_forum", locals: {pinned_forum: topic}
+ else
+ json.nil!
+ end
+ end
+ end
+ else
+ json.array! @topics.each do |topic|
+ case topic.type
+ when "Topic::ActivityForum"
+ json.partial! "activity_forum", locals: {activity_forum: topic}
+ when "Topic::Banner"
+ json.partial! "banner", locals: {banner: topic}
+ when "Topic::Card"
+ json.partial! "card", locals: {card: topic}
+ when "Topic::Cooperator"
+ json.partial! "cooperator", locals: {cooperator: topic}
+ when "Topic::ExcellentProject"
+ json.partial! "excellent_project", locals: {excellent_project: topic}
+ when "Topic::ExperienceForum"
+ json.partial! "experience_forum", locals: {experience_forum: topic}
+ when "Topic::PinnedForum"
+ json.partial! "pinned_forum", locals: {pinned_forum: topic}
+ else
+ json.nil!
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/config/configuration.yml.example b/config/configuration.yml.example
index 4671e4166..a5fba4ec7 100644
--- a/config/configuration.yml.example
+++ b/config/configuration.yml.example
@@ -63,6 +63,10 @@ default: &default
read_domain: ''
base_url: ''
+ forum:
+ domain: ''
+ base_url: '/api'
+
production:
<<: *default
# 中间层地址
diff --git a/config/routes.rb b/config/routes.rb
index d4e1ba1c5..4942bcfe5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -24,6 +24,7 @@ Rails.application.routes.draw do
resources :edu_settings
scope '/api' do
+ resources :topics, only: [:index]
namespace :ci do
resources :languages, only: [:index, :show] do
collection do
@@ -670,6 +671,16 @@ Rails.application.routes.draw do
namespace :admins do
mount Sidekiq::Web => '/sidekiq'
get '/', to: 'dashboards#index'
+ namespace :topic do
+ resources :activity_forums
+ resources :banners
+ resources :cards
+ resources :cooperators
+ resources :excellent_projects
+ resources :experience_forums
+ resources :pinned_forums
+ end
+
resources :project_statistics, only: [:index] do
collection do
get :visits_static
diff --git a/db/migrate/20211102065736_create_topics.rb b/db/migrate/20211102065736_create_topics.rb
new file mode 100644
index 000000000..f94ecacd1
--- /dev/null
+++ b/db/migrate/20211102065736_create_topics.rb
@@ -0,0 +1,11 @@
+class CreateTopics < ActiveRecord::Migration[5.2]
+ def change
+ create_table :topics do |t|
+ t.string :type
+ t.string :title
+ t.integer :uuid
+ t.string :url
+ t.integer :order_index
+ end
+ end
+end
diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb
new file mode 100644
index 000000000..b8c5a8e0c
--- /dev/null
+++ b/spec/models/topic_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe Topic, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end