diff --git a/app/assets/javascripts/admins/page_themes.js b/app/assets/javascripts/admins/page_themes.js
new file mode 100644
index 00000000..1663fb90
--- /dev/null
+++ b/app/assets/javascripts/admins/page_themes.js
@@ -0,0 +1,3 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
+
diff --git a/app/assets/stylesheets/admins/page_themes.scss b/app/assets/stylesheets/admins/page_themes.scss
new file mode 100644
index 00000000..b47fedab
--- /dev/null
+++ b/app/assets/stylesheets/admins/page_themes.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the admins/page_themes controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/admins/page_themes_controller.rb b/app/controllers/admins/page_themes_controller.rb
new file mode 100644
index 00000000..6f7d8f4d
--- /dev/null
+++ b/app/controllers/admins/page_themes_controller.rb
@@ -0,0 +1,61 @@
+class Admins::PageThemesController < Admins::Topic::BaseController
+ before_action :finder_page_theme, only: [:edit, :update, :destroy]
+
+ def index
+ params[:sort_by] = params[:sort_by].presence || 'created_at'
+ params[:sort_direction] = params[:sort_direction].presence || 'desc'
+
+ page_themes = Admins::PageThemesQuery.call(params)
+
+ @page_themes = paginate page_themes
+ end
+
+ def show
+ render 'edit'
+ end
+
+ def edit
+ end
+
+ def create
+ @page_theme = PageTheme.new update_params
+
+ if @page_theme.save
+ save_image_file(params[:image_url], @page_theme)
+ redirect_to admins_page_themes_path
+ flash[:success] = "新增主题成功"
+ else
+ redirect_to admins_page_themes_path
+ flash[:danger] = "新增主题失败: #{@page_theme.errors.messages.values.flatten.join(',')}"
+ end
+ end
+
+ def destroy
+ if @page_theme.destroy
+ redirect_to admins_page_themes_path
+ flash[:success] = "删除主题成功"
+ else
+ redirect_to admins_page_themes_path
+ flash[:danger] = "删除主题失败"
+ end
+ end
+
+ def new
+ @page_theme = PageTheme.new
+ end
+
+ def update
+ @page_theme.update(update_params)
+ flash[:success] = '保存成功'
+ render 'edit'
+ end
+
+ private
+ def finder_page_theme
+ @page_theme = PageTheme.find(params[:id])
+ end
+
+ def update_params
+ params.require(:page_theme).permit(:language_frame, :name, :cate, :image_url, :clone_url)
+ end
+end
diff --git a/app/helpers/admins/page_themes_helper.rb b/app/helpers/admins/page_themes_helper.rb
new file mode 100644
index 00000000..721d9b78
--- /dev/null
+++ b/app/helpers/admins/page_themes_helper.rb
@@ -0,0 +1,2 @@
+module Admins::PageThemesHelper
+end
diff --git a/app/models/glcc_registration_task.rb b/app/models/glcc_registration_task.rb
index 7c8671e6..da0d7cfd 100644
--- a/app/models/glcc_registration_task.rb
+++ b/app/models/glcc_registration_task.rb
@@ -1,20 +1,27 @@
-
# == Schema Information
#
-# Table name: ignores
-# user_id
-# student_name
-# school
-# profession
-# location
-# grade
-# phone
-# mail
-# created_on
-# is_delete
-# prove_attachment_id
-# cancel_count
-# round
+# Table name: glcc_registration_task
+#
+# id :integer not null, primary key
+# reg_id :integer not null
+# task_name :string(255)
+# task_desc :text(16777215)
+# task_difficulty :integer
+# task_url :string(1000)
+# task_reward :string(255)
+# tutor_name :string(255)
+# tutor_mail :string(255)
+# tutor_phone :string(255)
+# created_on :datetime
+# is_delete :boolean default("0"), not null
+# sort_no :integer default("0")
+# locked :boolean default("0")
+# round :integer default("1"), not null
+# check_status :boolean default("0")
+#
+# Indexes
+#
+# idx_glcc_reg_id (reg_id)
#
class GlccRegistrationTask < ActiveRecord::Base
diff --git a/app/models/page_theme.rb b/app/models/page_theme.rb
new file mode 100644
index 00000000..33734622
--- /dev/null
+++ b/app/models/page_theme.rb
@@ -0,0 +1,18 @@
+# == Schema Information
+#
+# Table name: page_themes
+#
+# id :integer not null, primary key
+# name :string(255) not null
+# language_frame :integer default("0")
+# image_url :string(255)
+# clone_url :string(255) not null
+# order_index :integer default("0")
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
+class PageTheme < ApplicationRecord
+ enum language_frame: { hugo: 0, jeklly: 1, hexo: 2}
+ validates :name, presence: {message: "主题名不能为空"}, uniqueness: {message: "主题名已存在",scope: :language_frame}
+end
diff --git a/app/models/project.rb b/app/models/project.rb
index 17972dd5..5f9fcef6 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -120,6 +120,7 @@ class Project < ApplicationRecord
has_many :issues, dependent: :destroy
# has_many :user_grades, dependent: :destroy
has_many :attachments, as: :container, dependent: :destroy
+ has_one :page, dependent: :destroy
has_one :project_score, dependent: :destroy
has_many :versions, -> { order("versions.created_on DESC, versions.name DESC") }, dependent: :destroy
has_many :praise_treads, as: :praise_tread_object, dependent: :destroy
diff --git a/app/queries/admins/page_themes_query.rb b/app/queries/admins/page_themes_query.rb
new file mode 100644
index 00000000..72d40943
--- /dev/null
+++ b/app/queries/admins/page_themes_query.rb
@@ -0,0 +1,17 @@
+class Admins::PageThemesQuery < ApplicationQuery
+ include CustomSortable
+
+ attr_reader :params
+
+ sort_columns :created_at, default_by: :created_at, default_direction: :desc
+
+ def initialize(params)
+ @params = params
+ end
+
+ def call
+ language_frame = params[:language_frame].blank? ? [0..99] : params[:language_frame]
+ page_themes = PageTheme.where(language_frame: language_frame)
+ custom_sort(page_themes, params[:sort_by], params[:sort_direction])
+ end
+end
\ No newline at end of file
diff --git a/app/views/admins/page_themes/_form_modal.html.erb b/app/views/admins/page_themes/_form_modal.html.erb
new file mode 100644
index 00000000..5e12fc40
--- /dev/null
+++ b/app/views/admins/page_themes/_form_modal.html.erb
@@ -0,0 +1,61 @@
+
+
+
+
+ <%= simple_form_for(@page_theme, url: admins_page_themes_path(@page_theme)) do |p| %>
+
+
+
+ 建站工具
+
+ <% state_options = [['hugo', "hugo"], ['jeklly', "jeklly"],['hexo',"hexo"]] %>
+ <%= select_tag('page_theme[language_frame]', options_for_select(state_options), class: 'form-control') %>
+
+
+
+
+
+ 主题名 *
+
+ <%= p.text_field :name,class: "form-control input-lg",required: true%>
+
+
+
+ 仓库url
+
+ <%= p.text_field :clone_url, class: "form-control",placeholder: ""%>
+
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+ <% logo_img = @page_theme.image_url %>
+
+
+ <%= file_field_tag(:image_url, 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/page_themes/_list.html.erb b/app/views/admins/page_themes/_list.html.erb
new file mode 100644
index 00000000..98aac607
--- /dev/null
+++ b/app/views/admins/page_themes/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 建站工具
+ 主题名
+ 图片
+ 仓库url
+ 操作
+
+
+
+ <% if page_themes.present? %>
+ <% page_themes.each_with_index do |banner, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= banner.language_frame %>
+ <%= banner.name %>
+
+ <%= banner.clone_url %>
+
+ <%= link_to "编辑", edit_admins_page_theme_path(banner), remote: true, class: "action" %>
+ <%= link_to "删除", admins_page_theme_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: page_themes } %>
\ No newline at end of file
diff --git a/app/views/admins/page_themes/edit.js.erb b/app/views/admins/page_themes/edit.js.erb
new file mode 100644
index 00000000..a9f963c5
--- /dev/null
+++ b/app/views/admins/page_themes/edit.js.erb
@@ -0,0 +1,18 @@
+$("#page-themes-modals").html("<%= j render(partial: 'admins/page_themes/form_modal', locals: {type: 'update'}) %>")
+$(".page-themes-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/page_themes/index.html.erb b/app/views/admins/page_themes/index.html.erb
new file mode 100644
index 00000000..72ea4088
--- /dev/null
+++ b/app/views/admins/page_themes/index.html.erb
@@ -0,0 +1,21 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('主题管理') %>
+<% end %>
+
+
+
+
+ <%= render partial: 'admins/page_themes/list', locals: { page_themes: @page_themes } %>
+
+
+
diff --git a/app/views/admins/page_themes/index.js.erb b/app/views/admins/page_themes/index.js.erb
new file mode 100644
index 00000000..30ea36a4
--- /dev/null
+++ b/app/views/admins/page_themes/index.js.erb
@@ -0,0 +1 @@
+$('.page-themes-list-container').html("<%= j( render partial: 'admins/page_themes/list', locals: { page_themes: @page_themes } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/page_themes/new.js.erb b/app/views/admins/page_themes/new.js.erb
new file mode 100644
index 00000000..4c3d847d
--- /dev/null
+++ b/app/views/admins/page_themes/new.js.erb
@@ -0,0 +1,18 @@
+$("#page-themes-modals").html("<%= j render(partial: 'admins/page_themes/form_modal', locals: {type: 'create'}) %>")
+$(".page-themes-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/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb
index d1d39fcf..813e2338 100644
--- a/app/views/admins/shared/_sidebar.html.erb
+++ b/app/views/admins/shared/_sidebar.html.erb
@@ -32,6 +32,7 @@
<%= sidebar_item_group('#pages-submenu', '站点管理', icon: 'cogs') do %>
<%= sidebar_item(admins_identity_verifications_path, '身份审核列表', icon: 'user', controller: 'admins-identity_verifications') %>
<%= sidebar_item(admins_site_pages_path, '用户站点列表', icon: 'sitemap', controller: 'admins-site_pages') %>
+ <%= sidebar_item(admins_page_themes_path, '站点主题配置', icon: 'cogs', controller: 'admins-page_themes') %>
<% end %>
diff --git a/app/views/admins/site_pages/shared/_info_list.html.erb b/app/views/admins/site_pages/shared/_info_list.html.erb
index 34b2f932..c61b9165 100644
--- a/app/views/admins/site_pages/shared/_info_list.html.erb
+++ b/app/views/admins/site_pages/shared/_info_list.html.erb
@@ -29,8 +29,8 @@
<% end %>
- <%= link_to "/#{site_page.user.login}/#{site_page.project.identifier}", target: '_blank' do %>
- <%= overflow_hidden_span site_page.project.name, width: 100 %>
+ <%= link_to "/#{site_page.user.login}/#{site_page.project.try(:identifier)}", target: '_blank' do %>
+ <%= overflow_hidden_span site_page.project.try(:name), width: 100 %>
<% end %>
<%= display_text(site_page.state == true ? "正常" : "已关闭") %>
diff --git a/config/routes.rb b/config/routes.rb
index 6a291bf2..7b6c4d8b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -815,6 +815,7 @@ Rails.application.routes.draw do
resources :users_rank, only: [:index]
resources :identity_verifications
resources :site_pages
+ resources :page_themes
resources :projects_rank, only: [:index]
resources :sites
resources :edu_settings
diff --git a/db/migrate/20230823071725_create_page_themes.rb b/db/migrate/20230823071725_create_page_themes.rb
new file mode 100644
index 00000000..22cb7ab1
--- /dev/null
+++ b/db/migrate/20230823071725_create_page_themes.rb
@@ -0,0 +1,12 @@
+class CreatePageThemes < ActiveRecord::Migration[5.2]
+ def change
+ create_table :page_themes do |t|
+ t.string :name, null:false
+ t.integer :language_frame, default:0
+ t.string :image_url
+ t.string :clone_url, null:false
+ t.integer :order_index,default: 0
+ t.timestamps
+ end
+ end
+end
diff --git a/spec/controllers/admins/page_themes_controller_spec.rb b/spec/controllers/admins/page_themes_controller_spec.rb
new file mode 100644
index 00000000..8495627c
--- /dev/null
+++ b/spec/controllers/admins/page_themes_controller_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe Admins::PageThemesController, type: :controller do
+
+end
diff --git a/spec/helpers/admins/page_themes_helper_spec.rb b/spec/helpers/admins/page_themes_helper_spec.rb
new file mode 100644
index 00000000..94f85f0c
--- /dev/null
+++ b/spec/helpers/admins/page_themes_helper_spec.rb
@@ -0,0 +1,15 @@
+require 'rails_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Admins::PageThemesHelper. For example:
+#
+# describe Admins::PageThemesHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+RSpec.describe Admins::PageThemesHelper, type: :helper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
diff --git a/spec/models/page_theme_spec.rb b/spec/models/page_theme_spec.rb
new file mode 100644
index 00000000..42f66aca
--- /dev/null
+++ b/spec/models/page_theme_spec.rb
@@ -0,0 +1,5 @@
+require 'rails_helper'
+
+RSpec.describe PageTheme, type: :model do
+ pending "add some examples to (or delete) #{__FILE__}"
+end