pages 合并

This commit is contained in:
xxq250 2023-09-25 10:50:35 +08:00
commit 02b85859b5
109 changed files with 1736 additions and 280778 deletions

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -63,7 +63,7 @@ $(document).on('turbolinks:load', function() {
if(!valid) return;
$.ajax({
method: 'PATCH',
method: 'PUT',
dataType: 'json',
url: $form.attr('action'),
data: new FormData($form[0]),

View File

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

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,3 @@
// Place all the styles related to the admins/identity_verifications controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

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

View File

@ -0,0 +1,3 @@
// Place all the styles related to the admins/site_pages controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the identity_verifications controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the pages controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,35 @@
class Admins::IdentityVerificationsController < Admins::BaseController
before_action :finder_identity_verification, except: [:index]
def index
params[:sort_by] = params[:sort_by].presence || 'created_at'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
identity_verifications = Admins::IdentityVerificationQuery.call(params)
@identity_verifications = paginate identity_verifications.preload(:user)
end
def show
render 'edit'
end
def edit
end
def update
if @identity_verification.update(update_params)
redirect_to admins_identity_verifications_path
flash[:success] = "更新成功"
else
redirect_to admins_identity_verifications_path
flash[:danger] = "更新失败"
end
end
private
def finder_identity_verification
@identity_verification = IdentityVerification.find(params[:id])
@user = @identity_verification.user
end
def update_params
params.require(:identity_verification).permit(:state, :description)
end
end

View File

@ -0,0 +1,79 @@
class Admins::PageThemesController < Admins::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 theme_params
if @page_theme.save
save_image_file(params[:image])
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 PageTheme.where(language_frame: @page_theme.language_frame).count <= 1
flash[:danger] = "删除主题失败,必须存在一个主题"
return redirect_to admins_page_themes_path
end
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.attributes = theme_params
if @page_theme.save
save_image_file(params[:image])
redirect_to admins_page_themes_path
flash[:success] = "更新成功"
else
redirect_to admins_page_themes_path
flash[:danger] = "更新失败"
end
end
private
def finder_page_theme
@page_theme = PageTheme.find(params[:id])
end
def theme_params
params.require(:page_theme).permit(:language_frame, :name, :cate, :image_url, :clone_url, :order_index)
end
def save_image_file(file)
return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
file_path = Util::FileManage.source_disk_filename(@page_theme, "image")
File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
Util.write_file(file, file_path)
end
end

View File

@ -0,0 +1,46 @@
class Admins::SitePagesController < Admins::BaseController
before_action :finder_site_page, except: [:index]
def index
params[:sort_by] = params[:sort_by].presence || 'created_at'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
pages = Admins::SitePagesQuery.call(params)
@site_pages = paginate pages.preload(:user)
end
def show
render 'edit'
end
def edit
end
def destroy
if @site_page.destroy
redirect_to admins_site_pages_path
flash[:success] = "删除站点成功"
else
redirect_to admins_site_pages_path
flash[:danger] = "删除站点失败"
end
end
def update
@site_page.update(update_params)
flash[:success] = '保存成功'
render 'edit'
end
private
def finder_site_page
@site_page = Page.find(params[:id])
@user = @site_page.user
end
def update_params
params.require(:page).permit(:state, :state_description)
end
end

View File

@ -1,5 +1,5 @@
class Admins::UsersController < Admins::BaseController
before_action :finder_user, except: [:index]
before_action :finder_user, except: [:index]
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
@ -72,6 +72,6 @@ class Admins::UsersController < Admins::BaseController
def update_params
params.require(:user).permit(%i[lastname nickname gender technical_title is_shixun_marker
mail phone location location_city school_id department_id admin
password login])
password login website_permission])
end
end

View File

@ -0,0 +1,29 @@
class IdentityVerificationsController < ApplicationController
before_action :require_login
before_action :require_profile_completed, only: [:create]
def index
@id_verify = current_user.identity_verification
return render_ok({data:nil}) unless @id_verify
end
def create
return tip_exception(-1, "您已提交过身份审核,请勿重复提交") if IdentityVerification.exists?(user:current_user)
return tip_exception(-1, "身份证输入有误")unless create_params[:number] =~ User::VALID_NUMBER_REGEX
@id_verify = IdentityVerification.new(create_params)
@id_verify.user = current_user
@id_verify.save
end
def update
return tip_exception(-1, "身份证输入有误")unless create_params[:number] =~ User::VALID_NUMBER_REGEX
current_user.identity_verification.update(create_params.merge({ state: 0 }))
current_user.update(id_card_verify: false)
@id_verify = current_user.identity_verification
end
private
def create_params
params.permit(:number, :name, :card_front, :card_back, :hold_card_front, :hold_card_back)
end
end

View File

@ -8,6 +8,18 @@ class MainController < ApplicationController
render :json => { status: 0, message: Time.now.to_i }
end
def test_404
status_code = 404
status = status_code.to_s
fname = %w[404 403 422 500].include?(status) ? status : "unknown"
respond_to do |format|
format.html { render template: "/shared/#{fname}", handler: [:erb], status: status }
format.xml { render :xml => Laboratory.limit(1).to_xml, status: status }
format.all { render body: nil, status: status }
end
end
def index
domain_session = params[:_educoder_session]
if domain_session
@ -24,6 +36,8 @@ class MainController < ApplicationController
# TODO: 这块之后需要整合者架构重新变化统一跳转到index后再路由分发
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html'
elsif params[:path].to_s.include?("test_404")
test_404
else
render file: 'public/react/build/index.html', :layout => false, :content_type=> 'text/html'
end

View File

@ -5,8 +5,8 @@ class ProjectsController < ApplicationController
include Acceleratorable
before_action :require_login, except: %i[index branches branches_slice group_type_list simple show fork_users praise_users watch_users recommend banner_recommend about menu_list verify_auth_token]
before_action :require_profile_completed, only: [:create, :migrate,:verify_auth_token]
before_action :load_repository, except: %i[index group_type_list migrate create recommend banner_recommend verify_auth_token]
before_action :require_profile_completed, only: [:create, :migrate,:page_migrate,:verify_auth_token]
before_action :load_repository, except: %i[index group_type_list migrate page_migrate create recommend banner_recommend verify_auth_token]
before_action :authorizate_user_can_edit_project!, only: %i[update]
before_action :project_public?, only: %i[fork_users praise_users watch_users]
before_action :request_limit, only: %i[index]
@ -97,6 +97,48 @@ class ProjectsController < ApplicationController
tip_exception(e.message)
end
def page_migrate
return normal_status(-1, "您还未开通Page服务无法进行新建站点") unless current_user.id_card_verify
return normal_status(-1, "你已使用了 #{page_site_params[:identifier]} 作为page标识") if Page.exists?(identifier: page_site_params[:identifier], user: current_user)
Projects::MigrateForm.new(mirror_params).validate!
@project =
if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
source_clone_url = mirror_params[:clone_addr]
uid_logger("########## 已动加速器 ##########")
result = Gitea::Accelerator::MigrateService.call(mirror_params)
if result[:status] == :success
Rails.logger.info "########## 加速镜像成功 ########## "
Projects::MigrateService.call(current_user,
mirror_params.merge(source_clone_url: source_clone_url,
clone_addr: accelerator_url(mirror_params[:repository_name])))
else
Projects::MigrateService.call(current_user, mirror_params)
end
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
source_clone_url = mirror_params[:clone_addr]
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
uid_logger("########## 更改clone_addr ##########")
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
else
Projects::MigrateService.call(current_user, mirror_params)
end
if @project.present?
page = Page.new page_site_params
page.user = current_user
page.project = @project
end
if page.save
render json: page
end
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
end
def branches
return @branches = [] unless @project.forge?
@ -305,6 +347,10 @@ class ProjectsController < ApplicationController
:auth_password, :project_category_id, :project_language_id, :clone_addr, :private)
end
def page_site_params
params.permit(:site_name, :identifier,:language_frame,:theme)
end
def project_public?
return if @project.is_public?

View File

@ -0,0 +1,94 @@
class SitePagesController < ApplicationController
before_action :require_login, except: [:softbot_build, :themes]
before_action :require_profile_completed, only: [:create]
before_action :load_project, except: [:softbot_build, :index, :themes]
before_action :authenticate_user!, except: [:softbot_build, :index, :themes, :show]
before_action :authenticate_member!, only: [:show]
def index
pages = PageQuery.call(params,current_user)
@total_count = pages.size
@pages = paginate(pages)
end
def show
@page = Page.find_by(project_id: @project.id)
return render_ok({data:nil}) unless @page.present?
end
def create
return normal_status(-1, "你还未开通Page服务无法进行部署") unless current_user.website_permission
return normal_status(-1, "你已使用了 #{params[:identifier]} 作为page标识") if Page.exists?(identifier: params[:identifier], user: current_user)
return normal_status(-1, "该仓库已开通Page服务") if Page.exists?(project: @project)
@page = Page.new(create_params)
@page.user = current_user
@page.project = @project
@page.save
end
def build
return normal_status(-1, "你还未开通Page服务无法进行部署") unless current_user.website_permission
return normal_status(-1, "该仓库还未开通Page服务无法进行部署") unless Page.exists?(project: @project)
@page = Page.find params[:id]
return normal_status(-1, @page.state_description) unless @page.state
response_str = @page.deploy_page(params[:branch])
data = JSON.parse(response_str)["result"] || data = JSON.parse(response_str)["error"]
if data.to_s.include?("部署成功")
@page.update(last_build_at: Time.now, build_state: true, last_build_info: data)
else
@page.update(build_state:false, last_build_info: data)
end
render_ok({data: data.nil? ? nil : data.split("\n") })
end
def softbot_build
branch = params[:ref].split("/").last
user = User.find_by_login params[:repository][:owner][:login]
return normal_status(-1, "你还未开通Page服务无法进行部署") unless user.website_permission
project = Project.where(identifier: params[:repository][:name],user_id: user.id)
return normal_status(-1, "你没有权限操作") if project.owner?(user)
return normal_status(-1, "该仓库还未开通Page服务无法进行部署") if Page.exists?(user: user, project: project)
@page = Page.find_by(user: user, project: project)
response_str = @page.deploy_page(branch)
data = JSON.parse(response_str)["result"]
if data.nil?
data = JSON.parse(response_str)["error"]
end
if data.include?("部署成功")
@page.update(last_build_at: Time.now, build_state: true, last_build_info: data)
else
@page.update(build_state:false, last_build_info: data)
end
render_ok
end
def themes
# data = YAML.load_file(Rails.root.join('config/admins', 'page_themes.yml'))
# render_ok({themes:data[theme_params.downcase]})
@themes = PageTheme.where(language_frame:theme_params).order(order_index: :asc)
end
private
def authenticate_user!
unless @project.manager?(current_user) || current_user.admin?
return render_forbidden('你不是管理员,没有权限操作')
end
end
def authenticate_member!
unless @project.member?(current_user) || current_user.admin?
return render_forbidden('你不是成员,没有权限操作')
end
end
def theme_params
params[:language_frame] || "hugo"
end
def create_params
params.permit(:identifier, :language_frame, :theme, :site_name)
end
end

View File

@ -0,0 +1,2 @@
module Admins::IdentityVerificationsHelper
end

View File

@ -0,0 +1,2 @@
module Admins::PageThemesHelper
end

View File

@ -0,0 +1,2 @@
module Admins::SitePagesHelper
end

View File

@ -0,0 +1,2 @@
module IdentityVerificationsHelper
end

View File

@ -0,0 +1,2 @@
module PagesHelper
end

View File

@ -120,14 +120,25 @@ module RepositoriesHelper
s_regex_c = /`{1,2}[^`](.*?)`{1,2}/
s_regex = /```([\s\S]*?)```[\s]?/
s_regex_1 = /\[.*?\]\((.*?)\)/
# 变量图片相对路径
s_regex_2 = /\[.*?\]:(.*?)\n/
src_regex = /src=\"(.*?)\"/
src_regex_1 = /src=\'(.*?)\'/
src_regex_2 = /src = (.*?) /
src_regex_3 = /src= (.*?) /
src_regex_4 = /src =(.*?) /
src_regex_5 = /src =(.*?) /
ss_c = content.to_s.scan(s_regex_c)
ss = content.to_s.scan(s_regex)
ss_1 = content.to_s.scan(s_regex_1)
ss_2 = content.to_s.scan(s_regex_2)
ss_src = content.to_s.scan(src_regex)
ss_src_1 = content.to_s.scan(src_regex_1)
total_sources = {ss_c: ss_c,ss: ss, ss_1: ss_1, ss_src: ss_src, ss_src_1: ss_src_1}
ss_src_2 = content.to_s.scan(src_regex_2)
ss_src_3 = content.to_s.scan(src_regex_3)
ss_src_4 = content.to_s.scan(src_regex_4)
ss_src_5 = content.to_s.scan(src_regex_5)
total_sources = {ss_c: ss_c,ss: ss, ss_1: ss_1, ss_2: ss_2, ss_src: ss_src, ss_src_1: ss_src_1, ss_src_2: ss_src_2, ss_src_3: ss_src_3, ss_src_4: ss_src_4, ss_src_5: ss_src_5}
# total_sources.uniq!
total_sources.except(:ss, :ss_c).each do |k, sources|
sources.each do |s|
@ -148,7 +159,17 @@ module RepositoriesHelper
content = content.gsub("src=\"#{s[0]}\"", "src=\"#{s_content}\"")
when 'ss_src_1'
content = content.gsub("src=\'#{s[0]}\'", "src=\'#{s_content}\'")
else
when 'ss_src_2'
content = content.gsub("src = #{s[0]}", "src=\'#{s_content}\'")
when 'ss_src_3'
content = content.gsub("src= #{s[0]}", "src=\'#{s_content}\'")
when 'ss_src_4'
content = content.gsub("src =#{s[0]}", "src=\'#{s_content}\'")
when 'ss_src_5'
content = content.gsub("src=#{s[0]}", "src=\'#{s_content}\'")
when 'ss_2'
content = content.gsub(/]:#{s[0]}/, "]: #{s_content.to_s.gsub(" ","").gsub("\r", "")}")
else
content = content.gsub("(#{s[0]})", "(#{s_content})")
end
else
@ -160,7 +181,9 @@ module RepositoriesHelper
content = content.gsub("src=\"#{s[0]}\"", "src=\"/#{s_content}\"")
when 'ss_src_1'
content = content.gsub("src=\'#{s[0]}\'", "src=\'/#{s_content}\'")
else
when 'ss_2'
content = content.gsub(/]:#{s[0]}/, "]: /#{s_content.to_s.gsub(" ","").gsub("\r", "")}")
else
content = content.gsub("(#{s[0]})", "(/#{s_content})")
end
end

View File

@ -2,23 +2,24 @@
#
# Table name: bot
#
# id :integer not null, primary key
# bot_name :string(255)
# bot_des :text(4294967295)
# webhook :string(255)
# is_public :integer
# logo :string(255)
# state :integer
# client_id :string(255)
# client_secret :string(255)
# web_url :string(255)
# category :string(255)
# install_num :integer default("0")
# update_time :datetime not null
# create_time :datetime not null
# private_key :text(65535)
# uid :integer
# owner_id :integer
# id :integer not null, primary key
# bot_name :string(255) not null
# bot_des :text(4294967295)
# webhook :string(255) not null
# is_public :integer
# logo :string(255)
# state :integer
# client_id :string(255)
# client_secret :string(255)
# web_url :string(255)
# category :string(255)
# install_num :integer default("0")
# update_time :datetime not null
# create_time :datetime not null
# uid :integer
# owner_id :integer
# private_key :text(65535)
# oauth_callback_url :string(255) not null
#
# Indexes
#

View File

@ -2,13 +2,18 @@
#
# Table name: install_bot
#
# id :integer not null, primary key
# bot_id :integer not null
# installer_id :integer not null
# store_id :integer not null
# state :integer not null
# create_time :datetime not null
# update_time :datetime not null
# id :integer not null, primary key
# bot_id :integer not null
# installer_id :integer not null
# store_id :integer not null
# state :integer not null
# create_time :datetime not null
# update_time :datetime not null
# installer_login :string(255) not null
# store_repo :string(255) not null
# webhook_id :integer
# webhook_response_msg :text(65535)
# repo_owner :string(255)
#
# frozen_string_literal: true

View File

@ -48,6 +48,8 @@
# devops_step :integer default("0")
# sign_cla :boolean default("0")
# enabling_cla :boolean default("0")
# id_card_verify :boolean default("0")
# website_permission :boolean default("0")
#
# Indexes
#

View File

@ -1,17 +1,19 @@
# == Schema Information
#
# Table name: ignores
# Table name: glcc_medium_term_examine_material
#
# id :integer not null, primary key
# student_reg_id :integer not null
# task_id :integer not null
# defence_video_url :string(1000) not null
# code_or_pr_url :string(1000)
# PPT_attachment_id :integer not null
# term :integer
# created_on :datetime
# updated_on :datetime
# is_delete :boolean default("0"), not null
# round :integer default("1"), not null
#
# student_reg_id
# task_id
# defence_video_url
# code_or_pr_url
# PPT_attachment_id
# term
# created_on
# updated_on
# is_delete
# round
class GlccMediumTermExamineMaterial < ActiveRecord::Base
self.table_name = "glcc_medium_term_examine_material"

View File

@ -1,19 +1,21 @@
# == 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_student
#
# id :integer not null, primary key
# user_id :integer not null
# student_name :string(255)
# school :string(255)
# profession :string(255)
# location :string(255)
# grade :string(255)
# phone :string(255)
# mail :string(255)
# created_on :datetime
# is_delete :boolean default("0"), not null
# prove_attachment_id :integer
# cancel_count :integer default("0")
# round :integer default("1"), not null
#
class GlccRegistrationStudent < ActiveRecord::Base

View File

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

View File

@ -9,7 +9,6 @@
# agreement :text(65535)
# status :text(65535)
# help_center :text(65535)
# join_us :text(65535)
#
class Help < ApplicationRecord

View File

@ -0,0 +1,48 @@
# == Schema Information
#
# Table name: identity_verifications
#
# id :integer not null, primary key
# user_id :integer not null
# number :string(255) not null
# name :string(255) not null
# card_front :integer
# card_back :integer
# hold_card_front :integer
# hold_card_back :integer
# state :integer default("0")
# description :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_identity_verifications_on_number (number)
#
class IdentityVerification < ApplicationRecord
belongs_to :user
enum state: { "待审核": 0, "已通过": 1, "已拒绝": 2}
after_save do
if state == "已通过"
user.update(id_card_verify: true, website_permission: true)
end
end
def card_front_attachment
Attachment.find_by_id card_front
end
def card_back_attachment
Attachment.find_by_id card_back
end
def hold_card_front_attachment
Attachment.find_by_id hold_card_front
end
def hold_card_back_attachment
Attachment.find_by_id hold_card_back
end
end

View File

@ -1,3 +1,26 @@
# == Schema Information
#
# Table name: open_shixuns
#
# id :integer not null, primary key
# name :string(255)
# shixun_user_name :string(255)
# shixun_user_phone :string(255)
# shixun_user_mail :string(255)
# shixun_identifier :string(255)
# git_url :string(255)
# identifier :string(255)
# myshixun_git_url :string(255)
# myshixun_user_name :string(255)
# myshixun_user_phone :string(255)
# myshixun_user_mail :string(255)
#
# Indexes
#
# idx_email (myshixun_user_mail)
# idx_phone (myshixun_user_phone)
#
# for oauth2 application

View File

@ -48,6 +48,8 @@
# devops_step :integer default("0")
# sign_cla :boolean default("0")
# enabling_cla :boolean default("0")
# id_card_verify :boolean default("0")
# website_permission :boolean default("0")
#
# Indexes
#

56
app/models/page.rb Normal file
View File

@ -0,0 +1,56 @@
# == Schema Information
#
# Table name: pages
#
# id :integer not null, primary key
# user_id :integer not null
# project_id :integer not null
# identifier :string(255)
# site_name :string(255)
# language_frame :integer default("0")
# theme :string(255)
# last_build_at :datetime
# state :boolean default("1")
# state_description :string(255)
# created_at :datetime not null
# updated_at :datetime not null
# last_build_info :text(65535)
# build_state :boolean
#
# Indexes
#
# index_pages_on_project_id (project_id)
# index_pages_on_user_id (user_id)
#
class Page < ApplicationRecord
belongs_to :user
belongs_to :project
# language_frame 前端语言框架
enum language_frame: { hugo: 0, jekyll: 1, hexo: 2}
after_create do
PageService.genernate_user(user_id)
end
before_save do
if state_changed? && state == false
PageService.close_site(user_id, identifier)
end
end
def deploy_page(branch)
PageService.deploy_page(branch,self.id)
end
def url
@deploy_domain = EduSetting.find_by_name("site_page_deploy_domain").try(:value)
"http://#{user.login}.#{@deploy_domain}/#{identifier}"
end
def build_script_path
"#{language_frame}_build"
end
end

29
app/models/page_theme.rb Normal file
View File

@ -0,0 +1,29 @@
# == 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},length: {maximum: 255}
def image
page_image_url('image')
end
private
def page_image_url(type)
return nil unless Util::FileManage.exists?(self, type)
Util::FileManage.source_disk_file_url(self, type)
end
end

View File

@ -55,9 +55,9 @@
# default_branch :string(255) default("master")
# website :string(255)
# lesson_url :string(255)
# use_blockchain :boolean default("0")
# is_pinned :boolean default("0")
# recommend_index :integer default("0")
# use_blockchain :boolean default("0")
# pr_view_admin :boolean default("0")
#
# Indexes
@ -117,6 +117,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

View File

@ -15,23 +15,6 @@
# auto_users_trial :boolean default("0")
# shool_code :string(255)
# authorization_time :datetime
# ec_auth :integer default("0")
# identifier :string(255)
# is_online :boolean default("0")
# video_name :string(255)
# video_desc :string(255)
# course_link :string(255)
# course_name :string(255)
# partner_id :integer
# customer_id :integer
# school_property_id :integer
#
# Indexes
#
# index_schools_on_customer_id (customer_id)
# index_schools_on_identifier (identifier)
# index_schools_on_partner_id (partner_id)
# index_schools_on_school_property_id (school_property_id)
#
class School < ApplicationRecord

View File

@ -48,6 +48,8 @@
# devops_step :integer default("0")
# sign_cla :boolean default("0")
# enabling_cla :boolean default("0")
# id_card_verify :boolean default("0")
# website_permission :boolean default("0")
#
# Indexes
#
@ -120,6 +122,7 @@ class User < Owner
has_many :open_users, dependent: :destroy
has_one :wechat_open_user, class_name: 'OpenUsers::Wechat'
has_one :qq_open_user, class_name: 'OpenUsers::Qq'
has_one :identity_verification
accepts_nested_attributes_for :user_extension, update_only: true
has_many :fork_users, dependent: :destroy
@ -186,6 +189,8 @@ class User < Owner
has_many :user_clas, :dependent => :destroy
has_many :clas, through: :user_clas
has_many :pages, :dependent => :destroy
# Groups and active users
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
scope :like, lambda { |keywords|
@ -758,6 +763,7 @@ class User < Owner
if password
salt_password(password)
end
check_website_permission
end
def salt_password(clear_password)
@ -765,6 +771,13 @@ class User < Owner
self.hashed_password = User.hash_password("#{salt}#{User.hash_password clear_password}")
end
def check_website_permission
if website_permission_changed? && website_permission == false
self.pages.update_all(state: false, state_description:"因违规使用现关闭Page服务")
PageService.close_site(self.id)
end
end
def self.generate_salt
Gitlink::Utils.random_hex(16)
end

View File

@ -0,0 +1,17 @@
class Admins::IdentityVerificationQuery < 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
state = params[:state] == "all" ? [0,1,2] : params[:state].nil? ? [0] : params[:state].to_i
applies = IdentityVerification.where(state: state)
custom_sort(applies, params[:sort_by], params[:sort_direction])
end
end

View File

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

View File

@ -0,0 +1,24 @@
class Admins::SitePagesQuery < 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
state = params[:state].blank? ? [true,false] : params[:state]
pages = Page.joins(:user).where(state: state)
# 关键字检索
keyword = params[:keyword].to_s.strip.presence
if keyword
sql = 'users.nickname LIKE :keyword OR users.login LIKE :keyword OR users.mail LIKE :keyword OR users.phone LIKE :keyword'
pages = pages.where(sql, keyword: "%#{keyword}%")
end
custom_sort(pages, params[:sort_by], params[:sort_direction])
end
end

13
app/queries/page_query.rb Normal file
View File

@ -0,0 +1,13 @@
class PageQuery < ApplicationQuery
attr_reader :params
def initialize(params, user)
@user = user
@params = params
end
def call
pages = Page.where(user: @user).order(created_at: :desc)
pages
end
end

View File

@ -32,7 +32,7 @@ class Admins::UpdateUserService < ApplicationService
def user_attributes
params.slice(*%i[lastname nickname mail phone admin business is_test login
professional_certification authentication is_shixun_marker])
professional_certification authentication is_shixun_marker website_permission])
end
def user_extension_attributes

View File

@ -0,0 +1,58 @@
require 'net/http'
require 'uri'
class PageService
def self.get_deploykey()
@deploy_key = EduSetting.find_by_name("site_page_deploy_key").try(:value)
@deploy_domain = EduSetting.find_by_name("site_page_deploy_domain").try(:value)
end
def self.genernate_user(user_id)
get_deploykey()
Rails.logger.info "################### PageService genernate_user #{user_id}"
user = User.find user_id
if user.id_card_verify == true && user.website_permission == true
uri = URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=create_dir&owner=#{user.login.downcase}")
response = Net::HTTP.get_response(uri)
end
Rails.logger.info "################### PageService genernate_user end #{response.body}"
return response.body
end
def self.close_site(user_id,identifier=nil)
get_deploykey()
Rails.logger.info "################### PageService close_site #{user_id} / #{identifier}"
user = User.find user_id
uri = if identifier.present?
URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=remove_dir&owner=#{user.login.downcase}/#{identifier}/")
else
URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=remove_dir&owner=#{user.login.downcase}/")
end
response = Net::HTTP.get_response(uri)
Rails.logger.info "################### PageService close_site end #{response.body}"
return response.body
end
def self.deploy_page(branch, page_id)
get_deploykey()
Rails.logger.info "################### PageService deploy #{branch} for page #{page_id}"
page = Page.find page_id
user = page.user
project = page.project
owner = user.login.downcase
project_dir = page.identifier
repo_link = project.repository.url
repo = project.repository.identifier
branch = branch
script_path =page.build_script_path
if script_path.present?
uri = URI.parse("http://gitlink.#{@deploy_domain}/gitlink_execute_script?key=#{@deploy_key}&script_path=#{script_path}&project_dir=#{project_dir}&repo=#{repo}&repo_link=#{repo_link}&branch=#{branch}&owner=#{owner}")
response = Net::HTTP.get_response(uri)
Rails.logger.info "################### PageService deploy #{response.body}"
return response.body
end
end
end

View File

@ -0,0 +1,119 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('身份审核列表', admins_identity_verifications_path)
add_admin_breadcrumb('用户身份审核详情')
end
%>
<div class="box identity_verification-edit-container">
<div class="identity_verification-info mb-4 row">
<%= link_to "/#{@identity_verification.user.login}", class: 'user-info-avatar col-md-1', target: '_blank', data: { toggle: 'tooltip', title: '个人中心' } do %>
<img src="/<%= url_to_avatar(@user) %>" class="rounded-circle" width="80" height="80" />
<% end %>
<div class="d-flex flex-column justify-content-between col-md-3 user-info-content">
<div class="user-info-name flex"><%= @user.real_name %> | <%= @user.id %> | <%= @user.login %></div>
<div class="d-flex flex-row user-info-auth">
<% if @user.authentication? %>
<i class="fa fa-user text-success" data-toggle="tooltip" data-placement="bottom" title="已实名认证"></i>
<% elsif @user.process_real_name_apply.present? %>
<i class="fa fa-user text-danger" data-toggle="tooltip" data-placement="bottom" title="实名认证中"></i>
<% else %>
<i class="fa fa-user text-muted" data-toggle="tooltip" data-placement="bottom" title="未实名认证"></i>
<% end %>
<% if @user.professional_certification %>
<i class="fa fa-list-alt text-success" data-toggle="tooltip" data-placement="bottom" title="已职业认证"></i>
<% elsif @user.process_professional_apply.present? %>
<i class="fa fa-list-alt text-danger" data-toggle="tooltip" data-placement="bottom" title="职业认证中"></i>
<% else %>
<i class="fa fa-list-alt text-muted" data-toggle="tooltip" data-placement="bottom" title="未职业认证"></i>
<% end %>
<% if @user.phone.present? %>
<i class="fa fa-mobile text-success" data-toggle="tooltip" data-placement="bottom" title="已绑定手机"></i>
<% else %>
<i class="fa fa-mobile text-muted" data-toggle="tooltip" data-placement="bottom" title="未绑定手机"></i>
<% end %>
<% if @user.mail.present? %>
<i class="fa fa-envelope text-success" data-toggle="tooltip" data-placement="bottom" title="已绑定邮箱"></i>
<% else %>
<i class="fa fa-envelope text-muted" data-toggle="tooltip" data-placement="bottom" title="未绑定邮箱"></i>
<% end %>
</div>
<div class="user-info-last-login">最近登录:<%= @user.last_login_on&.strftime('%Y-%m-%d %H:%M') %></div>
</div>
</div>
<%= simple_form_for(@identity_verification, url: admins_identity_verification_path(@identity_verification)) do |f| %>
<div class="mt-4">
<h6>审核信息</h6>
<label>当前身份审核状态为 <b><%=@identity_verification.state %></b></label>
<div class="form-row">
<%= f.input :name, label: '姓名', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-11' , value: @identity_verification.name } %>
</div>
<div class="form-row">
<%= f.input :number, label: '身份证号', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-11' , value: @identity_verification.number } %>
</div>
<label>身份证正面: </label>
<div class="form-row">
<td>
<% if @identity_verification.card_front_attachment.present? %>
<%= image_tag("/api/attachments/#{@identity_verification.card_front}", width: 100, height: 100, class: 'preview-image auth-image', data: { toggle: 'tooltip', title: '点击预览' }) %>
<%else%>
<p> 图片无法展示,图片已丢失</p>
<%end%>
</td>
</div>
<label>身份证背面: </label>
<div class="form-row">
<td>
<% if @identity_verification.card_back_attachment.present? %>
<%= image_tag("/api/attachments/#{@identity_verification.card_back}", width: 100, height: 100, class: 'preview-image auth-image', data: { toggle: 'tooltip', title: '点击预览' }) %>
<%else%>
<p> 图片无法展示,图片已丢失</p>
<%end%>
</td>
</div>
<label>手持身份证正面: </label>
<div class="form-row">
<td>
<% if @identity_verification.hold_card_front_attachment.present? %>
<%= image_tag("/api/attachments/#{@identity_verification.hold_card_front}", width: 100, height: 100, class: 'preview-image auth-image', data: { toggle: 'tooltip', title: '点击预览' }) %>
<%else%>
<p> 图片无法展示,图片已丢失</p>
<%end%>
</td>
</div>
<label>手持身份证背面: </label>
<div class="form-row">
<td>
<% if @identity_verification.hold_card_back_attachment.present? %>
<%= image_tag("/api/attachments/#{@identity_verification.hold_card_back}", width: 100, height: 100, class: 'preview-image auth-image', data: { toggle: 'tooltip', title: '点击预览' }) %>
<%else%>
<p> 图片无法展示,图片已丢失</p>
<%end%>
</td>
</div>
<% unless @identity_verification.state == "已通过" %>
<div class="form-row">
<%= radio_button_tag("identity_verification[state]","已通过", required: 'required') %>通过  
<%= radio_button_tag("identity_verification[state]","已拒绝", required: 'required') %>拒绝
</div>
</br>
<div class="form-row">
<%= f.input :description, as: :text,label: '拒绝理由:(拒绝时请填写拒绝理由,可以为空)', wrapper_html: { class: 'col-md-12' }, input_html: { maxlength: 100, size: 40, class: 'col-md-11' , value: @identity_verification.description } %>
</div>
<div class="form-row mt-4">
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %>
<%= link_to '取消', admins_identity_verifications_path, class: 'btn btn-secondary px-4' %>
</div>
<% end %>
</b>
</div>
<% end %>
</div>

View File

@ -0,0 +1,21 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('身份审核列表', admins_identity_verifications_path) %>
<% end %>
<div class="box search-form-container user-list-form">
<%= form_tag(admins_identity_verifications_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group mr-2">
<label for="state">状态:</label>
<% state_options = [['待审核', 0], ['全部',"all"], ['已通过', 1], ['已拒绝', 2]] %>
<%= select_tag(:state, options_for_select(state_options), class: 'form-control') %>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
</div>
<div class="box admin-list-container identity-verifications-list-container">
<%= render partial: 'admins/identity_verifications/shared/info_list', locals: { identity_verifications: @identity_verifications } %>
</div>

View File

@ -0,0 +1 @@
$('.identity-verifications-list-container').html("<%= j( render partial: 'admins/identity_verifications/shared/info_list', locals: { identity_verifications: @identity_verifications } ) %>");

View File

@ -0,0 +1,35 @@
<table class="table table-hover identity-verifications-list-table">
<thead class="thead-light">
<tr>
<th width="10%">序号</th>
<th width="10%" class="text-left">昵称</th>
<th width="10%">审核状态</th>
<th width="10%"><%= sort_tag('创建于', name: 'created_at', path: admins_identity_verifications_path) %></th>
<th width="14%">操作</th>
</tr>
</thead>
<tbody>
<% if identity_verifications.present? %>
<% identity_verifications.each_with_index do |identity_verification, index| %>
<tr class="identity-verification-item-<%= identity_verification.id %>">
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
<td class="text-left">
<%= link_to "/#{identity_verification.user.login}", target: '_blank' do %>
<%= overflow_hidden_span identity_verification.user.real_name, width: 100 %>
<% end %>
</td>
<td><%= display_text(identity_verification.state) %></td>
<td><%= display_text(identity_verification.created_at&.strftime('%Y-%m-%d %H:%M')) %></td>
<td class="action-container">
<%= link_to "#{ identity_verification.state == "待审核" ? '审核' : "查看"}", edit_admins_identity_verification_path(identity_verification), class: 'action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: identity_verifications } %>

View File

@ -4,7 +4,7 @@
<% end %>
<div class="box edit-laboratory-setting-container">
<%= simple_form_for(@laboratory, url: admins_laboratory_laboratory_setting_path(@laboratory), method: 'patch', html: { enctype: 'multipart/form-data' }) do |f| %>
<%= simple_form_for(@laboratory, url: admins_laboratory_laboratory_setting_path(@laboratory), method: 'put', html: { enctype: 'multipart/form-data' }) do |f| %>
<% setting = @laboratory.laboratory_setting %>
<div class="form-group px-2 setting-item">

View File

@ -0,0 +1,60 @@
<div class="modal fade page-themes-change-modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><%= type == "create" ? "新增" : "编辑" %></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<%= form_for @page_theme, url: {controller: "page_themes", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
<div class="modal-body">
<% if type == "create"%>
<div class="form-group">
<label>
建站工具 <span class="ml10 color-orange mr20">*</span>
</label>
<% state_options = [['hugo', "hugo"], ['jeklly', "jeklly"],['hexo',"hexo"]] %>
<%= select_tag('page_theme[language_frame]', options_for_select(state_options), class: 'form-control') %>
</div>
<% end%>
<div class="form-group">
<label>
主题名 <span class="ml10 color-orange mr20">*</span>
</label>
<%= p.text_field :name, class: "form-control input-lg",required: true, maxlength: 100, size: 100 %>
</div>
<div class="form-group">
<label>
仓库url <span class="ml10 color-orange mr20">*</span>
</label>
<%= p.text_field :clone_url, class: "form-control",placeholder: "https://gitlink.org.cn/XXXX/xxxx.git",required: true, pattern: "https://gitlink.org.cn/.*"%>
</div>
<div class="form-group">
<label>
排序等级
</label>
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
</div>
<div class="logo-item">
<% logo_img = @page_theme.image %>
<div class="logo-item-left mr-3 <%= logo_img ? 'has-img' : '' %>">
<img class="logo-item-img nav-logo-img" src="<%= logo_img %>" style="<%= logo_img.present? ? '' : 'display: none' %>"/>
<%= file_field_tag(:image, accept: 'image/png,image/jpg,image/jpeg',style: "display: none", value: params[:image]) %>
<label for="image" class="logo-item-upload" data-toggle="tooltip" data-title="选择图片"></label>
</div>
<div class="logo-item-right">
<div class="logo-item-title flex-1">logo <span class="ml10 color-orange mr20">*</span></div>
<div>格式PNG、JPG、JPEG、SVG</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<%= p.submit "确认", class: "btn btn-primary submit-btn" %>
</div>
<% end %>
</div>
</div>
</div>

View File

@ -0,0 +1,35 @@
<table class="table table-hover text-center subject-list-table">
<thead class="thead-light">
<tr>
<th width="5%">序号</th>
<th width="10%">建站工具</th>
<th width="5%">顺序</th>
<th width="15%">主题名</th>
<th width="20%">图片</th>
<th width="25%">仓库url</th>
<th width="20%">操作</th>
</tr>
</thead>
<tbody>
<% if page_themes.present? %>
<% page_themes.each_with_index do |theme, index| %>
<tr class="page-theme-item-<%= theme.id %>">
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
<td><%= theme.language_frame %></td>
<td><%= theme.order_index %></td>
<td style="word-break: break-all;word-wrap: break-word;" ><%= theme.name %></td>
<td><img style="width:150px" src="<%= theme.image %>" /></td>
<td style="word-break: break-all;word-wrap: break-word;" ><a href="<%= theme.clone_url %>" target="_blank"><%= theme.clone_url %></a> </td>
<td class="action-container">
<%= link_to "编辑", edit_admins_page_theme_path(theme), remote: true, class: "action" %>
<%= link_to "删除", admins_page_theme_path(theme), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: page_themes } %>

View File

@ -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 {
}
});

View File

@ -0,0 +1,21 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('站点主题配置') %>
<% end %>
<div class="box search-form-container project-list-form">
<%= form_tag(admins_page_themes_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group mr-2">
<label for="language_frame">建站工具:</label>
<% state_options = [['全部',nil], ['hugo', 0], ['jeklly', 1],['hexo',2]] %>
<%= select_tag(:language_frame, options_for_select(state_options), class: 'form-control') %>
</div>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
<%= link_to "新增", new_admins_page_theme_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
</div>
<div class="box admin-list-container page-themes-list-container">
<%= render partial: 'admins/page_themes/list', locals: { page_themes: @page_themes } %>
</div>
<div id="page-themes-modals">
</div>

View File

@ -0,0 +1 @@
$('.page-themes-list-container').html("<%= j( render partial: 'admins/page_themes/list', locals: { page_themes: @page_themes } ) %>");

View File

@ -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 {
}
});

View File

@ -24,6 +24,16 @@
<%= sidebar_item_group('#user-submenu', '用户', icon: 'user') do %>
<li><%= sidebar_item(admins_users_path, '用户列表', icon: 'user', controller: 'admins-users') %></li>
<li><%= sidebar_item(admins_organizations_path, '组织列表', icon: 'user', controller: 'admins-organizations') %></li>
<% end %>
</li>
<li>
<%= sidebar_item_group('#pages-submenu', '站点管理', icon: 'cogs') do %>
<li><%= sidebar_item(admins_identity_verifications_path, '身份审核列表', icon: 'user', controller: 'admins-identity_verifications') %></li>
<li><%= sidebar_item(admins_site_pages_path, '用户站点列表', icon: 'sitemap', controller: 'admins-site_pages') %></li>
<li><%= sidebar_item(admins_page_themes_path, '站点主题配置', icon: 'cogs', controller: 'admins-page_themes') %></li>
<% end %>
</li>
<li>

View File

@ -0,0 +1,99 @@
<%
define_admin_breadcrumbs do
add_admin_breadcrumb('用户站点列表', admins_site_pages_path)
add_admin_breadcrumb('站点详情')
end
%>
<div class="box site_page-edit-container">
<div class="site_page-info mb-4 row">
<%= link_to "/#{@site_page.user.login}", class: 'user-info-avatar col-md-1', target: '_blank', data: { toggle: 'tooltip', title: '个人中心' } do %>
<img src="/<%= url_to_avatar(@user) %>" class="rounded-circle" width="80" height="80" />
<% end %>
<div class="d-flex flex-column justify-content-between col-md-3 user-info-content">
<div class="user-info-name flex"><%= @user.real_name %> | <%= @user.id %> | <%= @user.login %></div>
<div class="d-flex flex-row user-info-auth">
<% if @user.authentication? %>
<i class="fa fa-user text-success" data-toggle="tooltip" data-placement="bottom" title="已实名认证"></i>
<% elsif @user.process_real_name_apply.present? %>
<i class="fa fa-user text-danger" data-toggle="tooltip" data-placement="bottom" title="实名认证中"></i>
<% else %>
<i class="fa fa-user text-muted" data-toggle="tooltip" data-placement="bottom" title="未实名认证"></i>
<% end %>
<% if @user.professional_certification %>
<i class="fa fa-list-alt text-success" data-toggle="tooltip" data-placement="bottom" title="已职业认证"></i>
<% elsif @user.process_professional_apply.present? %>
<i class="fa fa-list-alt text-danger" data-toggle="tooltip" data-placement="bottom" title="职业认证中"></i>
<% else %>
<i class="fa fa-list-alt text-muted" data-toggle="tooltip" data-placement="bottom" title="未职业认证"></i>
<% end %>
<% if @user.phone.present? %>
<i class="fa fa-mobile text-success" data-toggle="tooltip" data-placement="bottom" title="已绑定手机"></i>
<% else %>
<i class="fa fa-mobile text-muted" data-toggle="tooltip" data-placement="bottom" title="未绑定手机"></i>
<% end %>
<% if @user.mail.present? %>
<i class="fa fa-envelope text-success" data-toggle="tooltip" data-placement="bottom" title="已绑定邮箱"></i>
<% else %>
<i class="fa fa-envelope text-muted" data-toggle="tooltip" data-placement="bottom" title="未绑定邮箱"></i>
<% end %>
</div>
<div class="user-info-last-login">最近登录:<%= @user.last_login_on&.strftime('%Y-%m-%d %H:%M') %></div>
</div>
</div>
<%= simple_form_for(@site_page, url: admins_site_page_path(@site_page)) do |f| %>
<div class="mt-4">
<label>当前用户的站点权限为: <b><%=@site_page.user.website_permission == true ? "正常" : "关闭,已被管理员强制关闭建站权限" %></b></label></br>
<label>当前站点状态为: <b><%=@site_page.state == true ? "正常" : "关闭,关闭理由为:#{@site_page.state_description}" %></b></label>
<div class="form-row">
<%= f.input :identifier, label: '站点标识', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-5' , value: @site_page.identifier } %>
</div>
<div class="form-row">
<%= f.input :site_name, label: '站点名', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-5' , value: @site_page.site_name } %>
</div>
<div class="form-row">
<%= f.input :language_frame, label: '建站工具', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, type:'text', class: 'col-md-5' , value: @site_page.language_frame } %>
</div>
<div class="form-row">
<%= f.input :theme, label: '主题', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-5' , value: @site_page.theme } %>
</div>
</br>
<div class="form-row">
<label>当前站点:</label>
<a href="<%= @site_page.url%>" target="_blank"> <%= @site_page.url%> </a>
</div>
</br>
<div class="form-row">
<label>是否关闭站点? </label>
<%= f.radio_button :state, 'false' %> 关闭
</div>
</br>
<div class="form-row">
<label>注意,因为关闭站点涉及操作另外一台服务器,所以站点关闭后<b>无法重新打开</b>,请谨慎操作, 关闭站点后该仓库再也不能进行 <b>开通站点、部署等</b>操作 </label>
</div>
</br>
<div class="form-row">
<%= f.input :state_description, as: :text,label: '关闭理由,如需关闭 理由不能为空', wrapper_html: { class: 'col-md-12' }, input_html: { maxlength: 100, size: 40, class: 'col-md-11' , value: @site_page.state_description } %>
</div>
<div class="form-row mt-4">
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %>
<%= link_to '取消', admins_site_pages_path, class: 'btn btn-secondary px-4' %>
</div>
</div>
<% end %>
</div>

View File

@ -0,0 +1,21 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('用户站点列表', admins_site_pages_path) %>
<% end %>
<div class="box search-form-container user-list-form">
<%= form_tag(admins_site_pages_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<div class="form-group mr-2">
<label for="state">状态:</label>
<% state_options = [['全部',nil], ['正常', true], ['已关闭', false]] %>
<%= select_tag(:state, options_for_select(state_options), class: 'form-control') %>
</div>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '输入用户 ID/姓名/邮箱/手机号 检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
</div>
<div class="box admin-list-container identity-site-pages-list-container">
<%= render partial: 'admins/site_pages/shared/info_list', locals: { site_pages: @site_pages } %>
</div>

View File

@ -0,0 +1 @@
$('.identity-site-pages-list-container').html("<%= j( render partial: 'admins/site_pages/shared/info_list', locals: { site_pages: @site_pages } ) %>");

View File

@ -0,0 +1,62 @@
<table class="table table-hover identity-verifications-list-table">
<thead class="thead-light">
<tr>
<th width="5%">序号</th>
<th width="5%" class="text-left">昵称</th>
<th width="10%" class="text-left">仓库</th>
<th width="5%">站点状态</th>
<th width="10%" class="text-left">站点名</th>
<th width="10%" class="text-left">站点标识</th>
<th width="10%" class="text-left">站点地址</th>
<th width="5%" class="text-left">建站工具</th>
<th width="10%" class="text-left">主题</th>
<th width="10%" class="text-left">上次部署时间</th>
<th width="10%"><%= sort_tag('创建于', name: 'created_at', path: admins_site_pages_path) %></th>
<th width="10%">操作</th>
</tr>
</thead>
<tbody>
<% if site_pages.present? %>
<% site_pages.each_with_index do |site_page, index| %>
<tr class="identity-verification-item-<%= site_page.id %>">
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
<td class="text-left">
<%= link_to "/#{site_page.user.login}", target: '_blank' do %>
<%= overflow_hidden_span site_page.user.real_name, width: 100 %>
<% end %>
</td>
<td class="text-left">
<%= 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 %>
</td>
<td><%= display_text(site_page.state == true ? "正常" : "已关闭") %></td>
<td style="word-break: break-all;word-wrap: break-word;"><%= display_text(site_page.site_name) %></td>
<td style="word-break: break-all;word-wrap: break-word;"><%= display_text(site_page.identifier) %></td>
<td class="text-left">
<%= link_to "#{site_page.url}", target: '_blank' do %>
<%= overflow_hidden_span site_page.url, width: 120 %>
<% end %>
</td>
<td><%= display_text(site_page.language_frame) %></td>
<td><%= display_text(site_page.theme) %></td>
<td><%= display_text(site_page.last_build_at&.strftime('%Y-%m-%d %H:%M')) %></td>
<td><%= display_text(site_page.created_at&.strftime('%Y-%m-%d %H:%M')) %></td>
<td class="action-container">
<%= link_to "查看", edit_admins_site_page_path(site_page), class: 'action' %>
<%= link_to "删除", admins_site_page_path(site_page), method: :delete, data:{confirm: "确认删除吗,删除后站点将无法访问?"}, class: "action" %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: site_pages } %>

View File

@ -92,8 +92,15 @@
</div>
</div>
<% end %>
<% if @user.id_card_verify %>
<div class="form-group check_boxes optional">
<%= f.label :role, label: '站点权限' %>
<div class="d-flex">
<%= f.input :website_permission, as: :boolean, label: "开通站点(<b>关闭后,将清除该用户所有站点信息,此操作不可逆,请谨慎操作! 请谨慎操作!! 请谨慎操作!!</b>".html_safe, checked_value: 1, unchecked_value: 0 %>
</div>
</div>
<% end %>
<div class="form-row">
<%= f.input :password, as: :password, label: '修改密码', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-sm-11', autocomplete: 'new-password' } %>
<%= f.input :password_confirmation, as: :password, label: '确认密码', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-sm-11', autocomplete: 'new-password' } %>
@ -101,7 +108,7 @@
</div>
<div class="form-row mt-4">
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4' %>
<%= f.button :submit, value: '保存', class: 'btn-primary mr-3 px-4 action' ,data:{confirm: "确认更改?"}%>
<%= link_to '取消', admins_users_path, class: 'btn btn-secondary px-4' %>
</div>
<% end %>

View File

@ -0,0 +1,10 @@
json.id id_verify.id
json.number id_verify.number
json.name id_verify.name
json.card_front id_verify.card_front
json.card_back id_verify.card_back
json.hold_card_front id_verify.hold_card_front
json.hold_card_back id_verify.hold_card_back
json.state id_verify.state
json.description id_verify.description
json.created_at id_verify.created_at.strftime("%Y-%m-%d %H:%M")

View File

@ -0,0 +1 @@
json.partial! 'info', locals: {id_verify: @id_verify}

View File

@ -0,0 +1 @@
json.partial! 'info', locals: {id_verify: @id_verify}

View File

@ -0,0 +1 @@
json.partial! 'info', locals: {id_verify: @id_verify}

View File

@ -0,0 +1,16 @@
json.id page.id
json.identifier page.identifier
json.owner page.user.login
json.repo page.project.identifier
json.user_id page.user_id
json.project_id page.project_id
json.site_name page.site_name
json.theme page.theme
json.state page.state
json.state_description page.state_description
json.language_frame page.language_frame
json.build_state page.build_state
json.last_build_info page.last_build_info.to_s.split("\n")
json.url page.url
json.created_at page.created_at.strftime("%Y-%m-%d %H:%M:%S")
json.last_build_at page.last_build_at.nil? ? nil : page.last_build_at.strftime("%Y-%m-%d %H:%M:%S")

View File

@ -0,0 +1 @@
json.partial! "info", page: @page

View File

@ -0,0 +1,4 @@
json.total_count @total_count
json.pages @pages.each do |page|
json.partial! 'info', locals: {page: page}
end

View File

@ -0,0 +1,6 @@
json.status 0
json.message "success"
json.data {
json.partial! 'info', locals: {page: @page}
}

View File

@ -0,0 +1,10 @@
json.total_count @themes.size
json.themes @themes.map{|e|
{
name: e.name,
language_frame: e.language_frame,
image: e.image,
clone_url: e.clone_url,
order_index: e.order_index,
}
}

View File

@ -30,3 +30,5 @@ json.is_new params[:login].present? && (UserAction.where(action_type: "sync_educ
json.nps EduSetting.get("nps-on-off-switch").to_s == 'true' && UserNp.where(user_id: current_user.id).where("created_at >= ?", (Time.now - 30.days).beginning_of_day ).blank?
json.open_blockchain EduSetting.get("open_blockchain_users").to_s.split(",").include?(@user.id.to_s) || EduSetting.get("open_blockchain_users").to_s.split(",").include?(@user.login)
json.sign_cla @user.sign_cla
json.id_card_verify @user.id_card_verify
json.website_permission @user.website_permission

View File

@ -0,0 +1,22 @@
hugo:
-
name: "默认主题"
imgage_url: "https://pic1.zhimg.com/50/v2-02ed5def1f25e0de21f40eb9f96d28b9_200x0.jpg?source=b6762063"
clone_url: "https://gitlink.org.cn/SiteTheme/hugo.git"
jekyll:
-
name: "默认主题"
imgage_url: "https://pic1.zhimg.com/50/v2-02ed5def1f25e0de21f40eb9f96d28b9_200x0.jpg?source=b6762063"
clone_url: "https://gitlink.org.cn/SiteTheme/hugo.git"
hexo:
-
name: "默认主题"
imgage_url: "https://pic1.zhimg.com/50/v2-02ed5def1f25e0de21f40eb9f96d28b9_200x0.jpg?source=b6762063"
clone_url: "https://gitlink.org.cn/SiteTheme/hexo.git"
-
name: "Icarus"
imgage_url: "https://pic1.zhimg.com/50/v2-02ed5def1f25e0de21f40eb9f96d28b9_200x0.jpg?source=b6762063"
clone_url: "https://gitlink.org.cn/SiteTheme/hexo-theme-icarus.git"

View File

@ -89,7 +89,7 @@ Rails.application.routes.draw do
resources :project_rank, only: [:index]
resources :user_rank, only: [:index]
resources :nps, only: [:create]
resources :statistic, only: [:index] do
collection do
get :platform_profile
@ -239,6 +239,7 @@ Rails.application.routes.draw do
collection do
post :migrate
post :page_migrate
get :group_type_list
get :recommend
get :banner_recommend
@ -479,6 +480,16 @@ Rails.application.routes.draw do
end
end
end
resources :identity_verifications
resources :site_pages do
member do
post :build
end
collection do
post :softbot_build
get :themes
end
end
namespace :traces do
resources :trace_users, only: [:create]
@ -802,6 +813,9 @@ Rails.application.routes.draw do
end
end
resources :users_rank, only: [:index]
resources :identity_verifications
resources :site_pages
resources :page_themes
resources :projects_rank, only: [:index]
resources :sites
resources :edu_settings

View File

@ -0,0 +1,16 @@
class CreatePages < ActiveRecord::Migration[5.2]
def change
create_table :pages do |t|
t.integer :user_id, null:false, index:true
t.integer :project_id, null:false, index:true
t.string :identifier
t.string :site_name
t.integer :language_frame, default: 0
t.string :theme
t.datetime :last_build_at
t.boolean :state, default: true
t.string :state_description
t.timestamps
end
end
end

View File

@ -0,0 +1,16 @@
class CreateIdentityVerifications < ActiveRecord::Migration[5.2]
def change
create_table :identity_verifications do |t|
t.integer :user_id, null:false, index: true
t.string :number, null:false
t.string :name, null:false
t.integer :card_front
t.integer :card_back
t.integer :hold_card_front
t.integer :hold_card_back
t.integer :state, default: 0
t.string :description
t.timestamps
end
end
end

View File

@ -0,0 +1,6 @@
class AddIdCardVerifyToUsers < ActiveRecord::Migration[5.2]
def change
add_column :users, :id_card_verify, :boolean, default: false
add_column :users, :website_permission, :boolean, default: false
end
end

View File

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

View File

@ -0,0 +1,6 @@
class AddLastBuildInfoAndStateToPages < ActiveRecord::Migration[5.2]
def change
add_column :pages, :last_build_info, :text
add_column :pages, :build_state, :boolean
end
end

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Admins::IdentityVerificationsController, type: :controller do
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Admins::PageThemesController, type: :controller do
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Admins::SitePagesController, type: :controller do
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe IdentityVerificationsController, type: :controller do
end

Some files were not shown because too many files have changed in this diff Show More