FIX 解决featrue_homepage分支代码冲突
This commit is contained in:
commit
9d05973700
|
@ -51,6 +51,51 @@ http://localhost:3000/api/accounts/remote_register | jq
|
||||||
|-- token |string|用户token|
|
|-- token |string|用户token|
|
||||||
|
|
||||||
|
|
||||||
|
返回值
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success",
|
||||||
|
"user": {
|
||||||
|
"id": 36400,
|
||||||
|
"token": "8c87a80d9cfacc92fcb2451845104f35119eda96"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
#### 独立注册接口
|
||||||
|
```
|
||||||
|
POST accounts/register
|
||||||
|
```
|
||||||
|
*示例*
|
||||||
|
```bash
|
||||||
|
curl -X POST \
|
||||||
|
-d "login=2456233122@qq.com" \
|
||||||
|
-d "password=djs_D_00001" \
|
||||||
|
-d "namespace=16895620" \
|
||||||
|
-d "code=forge" \
|
||||||
|
http://localhost:3000/api/accounts/remote_register | jq
|
||||||
|
```
|
||||||
|
*请求参数说明:*
|
||||||
|
|
||||||
|
|参数名|必选|类型|说明|
|
||||||
|
|-|-|-|-|
|
||||||
|
|login |是|string |邮箱或者手机号 |
|
||||||
|
|namespace |是|string |登录名 |
|
||||||
|
|password |是|string |密码 |
|
||||||
|
|code |是|string |验证码 |
|
||||||
|
|
||||||
|
|
||||||
|
*返回参数说明:*
|
||||||
|
|
||||||
|
|参数名|类型|说明|
|
||||||
|
|-|-|-|
|
||||||
|
|user|json object |返回数据|
|
||||||
|
|-- id |int |用户id |
|
||||||
|
|-- token |string|用户token|
|
||||||
|
|
||||||
|
|
||||||
返回值
|
返回值
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
@ -1,4 +1,5 @@
|
||||||
class AccountsController < ApplicationController
|
class AccountsController < ApplicationController
|
||||||
|
include ApplicationHelper
|
||||||
|
|
||||||
#skip_before_action :check_account, :only => [:logout]
|
#skip_before_action :check_account, :only => [:logout]
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@ class AccountsController < ApplicationController
|
||||||
# 其他平台同步注册的用户
|
# 其他平台同步注册的用户
|
||||||
def remote_register
|
def remote_register
|
||||||
username = params[:username]&.gsub(/\s+/, "")
|
username = params[:username]&.gsub(/\s+/, "")
|
||||||
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.is_reversed(username).present?
|
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||||
email = params[:email]&.gsub(/\s+/, "")
|
email = params[:email]&.gsub(/\s+/, "")
|
||||||
password = params[:password]
|
password = params[:password]
|
||||||
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
|
||||||
|
@ -109,67 +110,46 @@ class AccountsController < ApplicationController
|
||||||
# 用户注册
|
# 用户注册
|
||||||
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
|
||||||
# params[:login] 邮箱或者手机号
|
# params[:login] 邮箱或者手机号
|
||||||
|
# params[:namespace] 登录名
|
||||||
# params[:code] 验证码
|
# params[:code] 验证码
|
||||||
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
# code_type 1:注册手机验证码 8:邮箱注册验证码
|
||||||
# 本地forge注册入口
|
# 本地forge注册入口需要重新更改逻辑
|
||||||
def register
|
def register
|
||||||
|
# type只可能是1或者8
|
||||||
|
user = nil
|
||||||
begin
|
begin
|
||||||
# 查询验证码是否正确;type只可能是1或者8
|
Register::Form.new(register_params).validate!
|
||||||
type = phone_mail_type(params[:login].strip)
|
|
||||||
# code = params[:code].strip
|
|
||||||
|
|
||||||
if type == 1
|
user = Users::RegisterService.call(register_params)
|
||||||
uid_logger("start register by phone: type is #{type}")
|
password = register_params[:password].strip
|
||||||
pre = 'p'
|
|
||||||
email = nil
|
|
||||||
phone = params[:login]
|
|
||||||
# verifi_code = VerificationCode.where(phone: phone, code: code, code_type: 1).last
|
|
||||||
# TODO: 暂时限定邮箱注册
|
|
||||||
return normal_status(-1, '只支持邮箱注册')
|
|
||||||
else
|
|
||||||
uid_logger("start register by email: type is #{type}")
|
|
||||||
pre = 'm'
|
|
||||||
email = params[:login]
|
|
||||||
phone = nil
|
|
||||||
return normal_status(-1, "该邮箱已注册") if User.exists?(mail: params[:login])
|
|
||||||
return normal_status(-1, "邮箱格式错误") unless params[:login] =~ CustomRegexp::EMAIL
|
|
||||||
# verifi_code = VerificationCode.where(email: email, code: code, code_type: 8).last
|
|
||||||
end
|
|
||||||
# uid_logger("start register: verifi_code is #{verifi_code}, code is #{code}, time is #{Time.now.to_i - verifi_code.try(:created_at).to_i}")
|
|
||||||
# check_code = (verifi_code.try(:code) == code.strip && (Time.now.to_i - verifi_code.created_at.to_i) <= 10*60)
|
|
||||||
# todo 上线前请删除万能验证码"513231"
|
|
||||||
return normal_status(-1, "8~16位密码,支持字母数字和符号") unless params[:password] =~ CustomRegexp::PASSWORD
|
|
||||||
|
|
||||||
code = generate_identifier User, 8, pre
|
# gitea用户注册, email, username, password
|
||||||
login = pre + code
|
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
||||||
|
|
||||||
is_admin = !User.exists?(type: 'User')
|
|
||||||
@user = User.new(admin: is_admin, login: login, mail: email, phone: phone, type: "User")
|
|
||||||
@user.password = params[:password]
|
|
||||||
# 现在因为是验证码,所以在注册的时候就可以激活
|
|
||||||
@user.activate
|
|
||||||
# 必须要用save操作,密码的保存是在users中
|
|
||||||
|
|
||||||
interactor = Gitea::RegisterInteractor.call({username: login, email: email, password: params[:password]})
|
|
||||||
if interactor.success?
|
if interactor.success?
|
||||||
gitea_user = interactor.result
|
gitea_user = interactor.result
|
||||||
result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
|
result = Gitea::User::GenerateTokenService.call(user.login, password)
|
||||||
@user.gitea_token = result['sha1']
|
user.gitea_token = result['sha1']
|
||||||
@user.gitea_uid = gitea_user[:body]['id']
|
user.gitea_uid = gitea_user[:body]['id']
|
||||||
if @user.save!
|
if user.save!
|
||||||
# set user for admin role
|
UserExtension.create!(user_id: user.id)
|
||||||
if @user.admin?
|
successful_authentication(user)
|
||||||
sync_params = { email: @user.mail, admin: true }
|
render_ok
|
||||||
Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
|
||||||
end
|
|
||||||
UserExtension.create!(user_id: @user.id)
|
|
||||||
successful_authentication(@user)
|
|
||||||
normal_status("注册成功")
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
tip_exception(-1, interactor.error)
|
tip_exception(-1, interactor.error)
|
||||||
end
|
end
|
||||||
|
rescue Register::BaseForm::EmailError => e
|
||||||
|
render_error(-2, e.message)
|
||||||
|
rescue Register::BaseForm::LoginError => e
|
||||||
|
render_error(-3, e.message)
|
||||||
|
rescue Register::BaseForm::PhoneError => e
|
||||||
|
render_error(-4, e.message)
|
||||||
|
rescue Register::BaseForm::PasswordFormatError => e
|
||||||
|
render_error(-5, e.message)
|
||||||
|
rescue Register::BaseForm::VerifiCodeError => e
|
||||||
|
render_error(-6, e.message)
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
Gitea::User::DeleteService.call(user.login) unless user.nil?
|
||||||
uid_logger_error(e.message)
|
uid_logger_error(e.message)
|
||||||
tip_exception(-1, e.message)
|
tip_exception(-1, e.message)
|
||||||
end
|
end
|
||||||
|
@ -304,7 +284,7 @@ class AccountsController < ApplicationController
|
||||||
|
|
||||||
# 发送验证码
|
# 发送验证码
|
||||||
# params[:login] 手机号或者邮箱号
|
# params[:login] 手机号或者邮箱号
|
||||||
# params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
# params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
|
||||||
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
|
||||||
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
|
||||||
def get_verification_code
|
def get_verification_code
|
||||||
|
@ -318,19 +298,22 @@ class AccountsController < ApplicationController
|
||||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
|
||||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||||
|
|
||||||
|
logger.info "########### 验证码:#{verification_code}"
|
||||||
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
|
||||||
|
|
||||||
# 记录验证码
|
# 记录验证码
|
||||||
check_verification_code(verification_code, send_type, value)
|
check_verification_code(verification_code, send_type, value)
|
||||||
sucess_status
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
# 1 手机类型;0 邮箱类型
|
# check user's login or email or phone is used
|
||||||
# 注意新版的login是自动名生成的
|
# params[:value] 手机号或者邮箱号或者登录名
|
||||||
def phone_mail_type value
|
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||||
value =~ /^1\d{10}$/ ? 1 : 0
|
def check
|
||||||
|
Register::CheckColumnsForm.new(check_params).validate!
|
||||||
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||||
|
@ -376,4 +359,13 @@ class AccountsController < ApplicationController
|
||||||
def account_params
|
def account_params
|
||||||
params.require(:account).permit(:login, :password)
|
params.require(:account).permit(:login, :password)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_params
|
||||||
|
params.permit(:type, :value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def register_params
|
||||||
|
params.permit(:login, :namespace, :password, :code)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,10 @@ class Admins::SystemNotificationsController < Admins::BaseController
|
||||||
@notifications = paginate(notifications)
|
@notifications = paginate(notifications)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def history
|
||||||
|
@users = @notification.users
|
||||||
|
end
|
||||||
|
|
||||||
def new
|
def new
|
||||||
@notification = SystemNotification.new
|
@notification = SystemNotification.new
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,4 +1,6 @@
|
||||||
class Admins::UsersController < Admins::BaseController
|
class Admins::UsersController < Admins::BaseController
|
||||||
|
before_action :finder_user, except: [:index]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
params[:sort_by] = params[:sort_by].presence || 'created_on'
|
||||||
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
params[:sort_direction] = params[:sort_direction].presence || 'desc'
|
||||||
|
@ -8,12 +10,9 @@ class Admins::UsersController < Admins::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@user = User.find(params[:id])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@user = User.find(params[:id])
|
|
||||||
|
|
||||||
Admins::UpdateUserService.call(@user, update_params)
|
Admins::UpdateUserService.call(@user, update_params)
|
||||||
flash[:success] = '保存成功'
|
flash[:success] = '保存成功'
|
||||||
redirect_to edit_admins_user_path(@user)
|
redirect_to edit_admins_user_path(@user)
|
||||||
|
@ -26,43 +25,47 @@ class Admins::UsersController < Admins::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
User.find(params[:id]).destroy!
|
@user.destroy!
|
||||||
|
Gitea::User::DeleteService.call(@user.login)
|
||||||
|
|
||||||
render_delete_success
|
render_delete_success
|
||||||
end
|
end
|
||||||
|
|
||||||
def lock
|
def lock
|
||||||
User.find(params[:id]).lock!
|
@user.lock!
|
||||||
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def unlock
|
def unlock
|
||||||
User.find(params[:id]).activate!
|
@user.activate!
|
||||||
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
def reward_grade
|
def reward_grade
|
||||||
user = User.find(params[:user_id])
|
|
||||||
return render_unprocessable_entity('金币数量必须大于0') if params[:grade].to_i <= 0
|
return render_unprocessable_entity('金币数量必须大于0') if params[:grade].to_i <= 0
|
||||||
|
|
||||||
RewardGradeService.call(user, container_id: user.id, container_type: 'Feedback', score: params[:grade].to_i, not_unique: true)
|
RewardGradeService.call(@user, container_id: @user.id, container_type: 'Feedback', score: params[:grade].to_i, not_unique: true)
|
||||||
|
|
||||||
render_ok(grade: user.grade)
|
render_ok(grade: @user.grade)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_login_times
|
def reset_login_times
|
||||||
User.find(params[:id]).reset_login_times!
|
@user.reset_login_times!
|
||||||
|
|
||||||
render_ok
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def finder_user
|
||||||
|
@user = User.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
def update_params
|
def update_params
|
||||||
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
|
params.require(:user).permit(%i[lastname nickname gender identity technical_title student_id is_shixun_marker
|
||||||
mail phone location location_city school_id department_id admin business is_test
|
mail phone location location_city school_id department_id admin business is_test
|
||||||
password professional_certification authentication])
|
password professional_certification authentication login])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,49 +70,11 @@ class ApplicationController < ActionController::Base
|
||||||
(current_user.professional_certification && (ue.teacher? || ue.professional?))
|
(current_user.professional_certification && (ue.teacher? || ue.professional?))
|
||||||
end
|
end
|
||||||
|
|
||||||
def shixun_marker
|
|
||||||
unless current_user.is_shixun_marker? || current_user.admin_or_business?
|
|
||||||
tip_exception(403, "..")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# 实训的访问权限
|
|
||||||
def shixun_access_allowed
|
|
||||||
if !current_user.shixun_permission(@shixun)
|
|
||||||
tip_exception(403, "..")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def admin_or_business?
|
def admin_or_business?
|
||||||
User.current.admin? || User.current.business?
|
User.current.admin? || User.current.business?
|
||||||
end
|
end
|
||||||
|
|
||||||
# 访问课堂时没权限直接弹加入课堂的弹框 :409
|
|
||||||
def user_course_identity
|
|
||||||
@user_course_identity = current_user.course_identity(@course)
|
|
||||||
if @user_course_identity > Course::STUDENT && @course.is_public == 0
|
|
||||||
tip_exception(401, "..") unless User.current.logged?
|
|
||||||
check_account
|
|
||||||
tip_exception(@course.excellent ? 410 : 409, "您没有权限进入")
|
|
||||||
end
|
|
||||||
if @user_course_identity > Course::CREATOR && @user_course_identity <= Course::STUDENT && @course.tea_id != current_user.id
|
|
||||||
# 实名认证和职业认证的身份判断
|
|
||||||
tip_exception(411, "你的实名认证和职业认证审核未通过") if @course.authentication &&
|
|
||||||
@course.professional_certification && (!current_user.authentication && !current_user.professional_certification)
|
|
||||||
tip_exception(411, "你的实名认证审核未通过") if @course.authentication && !current_user.authentication
|
|
||||||
tip_exception(411, "你的职业认证审核未通过") if @course.professional_certification && !current_user.professional_certification
|
|
||||||
end
|
|
||||||
uid_logger("###############user_course_identity:#{@user_course_identity}")
|
|
||||||
end
|
|
||||||
|
|
||||||
# 题库的访问权限
|
|
||||||
def bank_visit_auth
|
|
||||||
tip_exception(-2,"未通过职业认证") if current_user.is_teacher? && !current_user.certification_teacher? && !current_user.admin_or_business? && @bank.user_id != current_user.id && @bank.is_public
|
|
||||||
tip_exception(403, "无权限") unless @bank.user_id == current_user.id || current_user.admin_or_business? ||
|
|
||||||
(current_user.certification_teacher? && @bank.is_public)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# 判断用户的邮箱或者手机是否可用
|
# 判断用户的邮箱或者手机是否可用
|
||||||
# params[:type] 1: 注册;2:忘记密码;3:绑定
|
# params[:type] 1: 注册;2:忘记密码;3:绑定
|
||||||
def check_mail_and_phone_valid login, type
|
def check_mail_and_phone_valid login, type
|
||||||
|
@ -120,16 +82,16 @@ class ApplicationController < ActionController::Base
|
||||||
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
|
login =~ /^[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])$/
|
||||||
tip_exception(-2, "请输入正确的手机号或邮箱")
|
tip_exception(-2, "请输入正确的手机号或邮箱")
|
||||||
end
|
end
|
||||||
# 考虑到安全参数问题,多一次查询,去掉Union
|
|
||||||
user = User.where(phone: login).first || User.where(mail: login).first
|
user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
|
||||||
if type.to_i == 1 && !user.nil?
|
if user_exist && type.to_i == 1
|
||||||
tip_exception(-2, "该手机号码或邮箱已被注册")
|
tip_exception(-2, "该手机号码或邮箱已被注册")
|
||||||
elsif type.to_i == 2 && user.nil?
|
elsif type.to_i == 2 && !user_exist
|
||||||
tip_exception(-2, "该手机号码或邮箱未注册")
|
tip_exception(-2, "该手机号码或邮箱未注册")
|
||||||
elsif type.to_i == 3 && user.present?
|
elsif type.to_i == 3 && user_exist
|
||||||
tip_exception(-2, "该手机号码或邮箱已绑定")
|
tip_exception(-2, "该手机号码或邮箱已绑定")
|
||||||
end
|
end
|
||||||
sucess_status
|
render_ok
|
||||||
end
|
end
|
||||||
|
|
||||||
# 发送及记录激活码
|
# 发送及记录激活码
|
||||||
|
@ -186,26 +148,6 @@ class ApplicationController < ActionController::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_course
|
|
||||||
return normal_status(2, '缺少course_id参数!') if params[:course_id].blank?
|
|
||||||
@course = Course.find(params[:course_id])
|
|
||||||
tip_exception(404, "") if @course.is_delete == 1 && !current_user.admin_or_business?
|
|
||||||
rescue Exception => e
|
|
||||||
tip_exception(e.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def course_manager
|
|
||||||
return normal_status(403, '只有课堂管理员才有权限') if @user_course_identity > Course::CREATOR
|
|
||||||
end
|
|
||||||
|
|
||||||
def find_board
|
|
||||||
return normal_status(2, "缺少board_id参数") if params[:board_id].blank?
|
|
||||||
@board = Board.find(params[:board_id])
|
|
||||||
rescue Exception => e
|
|
||||||
uid_logger_error(e.message)
|
|
||||||
tip_exception(e.message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_type(object_type)
|
def validate_type(object_type)
|
||||||
normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
|
normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
|
||||||
end
|
end
|
||||||
|
@ -215,21 +157,6 @@ class ApplicationController < ActionController::Base
|
||||||
@page_size = params[:page_size] || 15
|
@page_size = params[:page_size] || 15
|
||||||
end
|
end
|
||||||
|
|
||||||
# 课堂教师权限
|
|
||||||
def teacher_allowed
|
|
||||||
logger.info("#####identity: #{current_user.course_identity(@course)}")
|
|
||||||
unless current_user.course_identity(@course) < Course::STUDENT
|
|
||||||
normal_status(403, "")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# 课堂教师、课堂管理员、超级管理员的权限(不包含助教)
|
|
||||||
def teacher_or_admin_allowed
|
|
||||||
unless current_user.course_identity(@course) < Course::ASSISTANT_PROFESSOR
|
|
||||||
normal_status(403, "")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def require_admin
|
def require_admin
|
||||||
normal_status(403, "") unless User.current.admin?
|
normal_status(403, "") unless User.current.admin?
|
||||||
end
|
end
|
||||||
|
@ -681,7 +608,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
def kaminari_paginate(relation)
|
def kaminari_paginate(relation)
|
||||||
limit = params[:limit] || params[:per_page]
|
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
|
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
|
||||||
|
|
||||||
relation.page(page).per(limit)
|
relation.page(page).per(limit)
|
||||||
|
@ -689,7 +616,7 @@ class ApplicationController < ActionController::Base
|
||||||
|
|
||||||
def kaminari_array_paginate(relation)
|
def kaminari_array_paginate(relation)
|
||||||
limit = params[:limit] || params[:per_page]
|
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
|
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
|
||||||
|
|
||||||
Kaminari.paginate_array(relation).page(page).per(limit)
|
Kaminari.paginate_array(relation).page(page).per(limit)
|
||||||
|
|
|
@ -3,8 +3,8 @@ module RenderHelper
|
||||||
render json: { status: 0, message: 'success' }.merge(data)
|
render json: { status: 0, message: 'success' }.merge(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_error(message = '')
|
def render_error(status = -1, message = '')
|
||||||
render json: { status: -1, message: message }
|
render json: { status: status, message: message }
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_not_acceptable(message = '请求已拒绝')
|
def render_not_acceptable(message = '请求已拒绝')
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.is_reversed(organization_params[:name]).present?
|
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
|
||||||
Organizations::CreateForm.new(organization_params).validate!
|
Organizations::CreateForm.new(organization_params).validate!
|
||||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,15 @@
|
||||||
|
class Users::SystemNotificationHistoriesController < Users::BaseController
|
||||||
|
before_action :private_user_resources!, only: [:create]
|
||||||
|
def create
|
||||||
|
@history = observed_user.system_notification_histories.new(system_notification_id: params[:system_notification_id])
|
||||||
|
if @history.save
|
||||||
|
render_ok
|
||||||
|
else
|
||||||
|
Rails.logger.info @history.errors.as_json
|
||||||
|
render_error(@history.errors.full_messages.join(","))
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
uid_logger_error(e.message)
|
||||||
|
tip_exception(e.message)
|
||||||
|
end
|
||||||
|
end
|
|
@ -199,6 +199,36 @@ await octokit.request('GET /api/users/:login/messages.json')
|
||||||
Success Data.
|
Success Data.
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
## 用户阅读系统通知
|
||||||
|
用户阅读系统通知
|
||||||
|
|
||||||
|
> 示例:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
curl -X POST http://localhost:3000/api/users/yystopf/system_notification_histories.json
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
await octokit.request('GET /api/users/:login/system_notification_histories.json')
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP 请求
|
||||||
|
`POST /api/users/:login/system_notification_histories.json`
|
||||||
|
|
||||||
|
### 请求字段说明:
|
||||||
|
参数 | 类型 | 字段说明
|
||||||
|
--------- | ----------- | -----------
|
||||||
|
|system_notification_id |integer |阅读的系统通知id |
|
||||||
|
|
||||||
|
> 返回的JSON示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": 0,
|
||||||
|
"message": "success"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 发送消息
|
## 发送消息
|
||||||
发送消息, 目前只支持atme
|
发送消息, 目前只支持atme
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,11 @@ class BaseForm
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_reversed_keyword(repository_name)
|
def check_reversed_keyword(repository_name)
|
||||||
raise "项目标识已被占用." if ReversedKeyword.is_reversed(repository_name).exists?
|
raise "项目标识已被占用." if ReversedKeyword.check_exists?(repository_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def strip(str)
|
||||||
|
str.to_s.strip.presence
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
module Register
|
||||||
|
class BaseForm < ::BaseForm
|
||||||
|
include ActiveModel::Model
|
||||||
|
|
||||||
|
Error = Class.new(StandardError)
|
||||||
|
EmailError = Class.new(Error)
|
||||||
|
LoginError = Class.new(Error)
|
||||||
|
PhoneError = Class.new(Error)
|
||||||
|
PasswordFormatError = Class.new(Error)
|
||||||
|
VerifiCodeError = Class.new(Error)
|
||||||
|
|
||||||
|
private
|
||||||
|
def check_login(login)
|
||||||
|
login = strip(login)
|
||||||
|
raise LoginError, "登录名格式有误" unless login =~ CustomRegexp::LOGIN
|
||||||
|
|
||||||
|
login_exist = Owner.exists?(login: login) || ReversedKeyword.check_exists?(login)
|
||||||
|
raise LoginError, '登录名已被使用' if login_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_mail(mail)
|
||||||
|
mail = strip(mail)
|
||||||
|
raise EmailError, "邮件格式有误" unless mail =~ CustomRegexp::EMAIL
|
||||||
|
|
||||||
|
mail_exist = Owner.exists?(mail: mail)
|
||||||
|
raise EmailError, '邮箱已被使用' if mail_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_phone(phone)
|
||||||
|
phone = strip(phone)
|
||||||
|
raise PhoneError, "手机号格式有误" unless phone =~ CustomRegexp::PHONE
|
||||||
|
|
||||||
|
phone_exist = Owner.exists?(phone: phone)
|
||||||
|
raise PhoneError, '手机号已被使用' if phone_exist
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_password(password)
|
||||||
|
password = strip(password)
|
||||||
|
raise PasswordFormatError, "8~16位密码,支持字母数字和符号" unless password =~ CustomRegexp::PASSWORD
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_verifi_code(verifi_code, code)
|
||||||
|
code = strip(code)
|
||||||
|
# return if code == "123123" # TODO 万能验证码,用于测试
|
||||||
|
|
||||||
|
raise VerifiCodeError, "验证码不正确" if verifi_code&.code != code
|
||||||
|
raise VerifiCodeError, "验证码已失效" if !verifi_code&.effective?
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,19 @@
|
||||||
|
module Register
|
||||||
|
class CheckColumnsForm < Register::BaseForm
|
||||||
|
attr_accessor :type, :value
|
||||||
|
|
||||||
|
validates :type, presence: true, numericality: true
|
||||||
|
validates :value, presence: true
|
||||||
|
validate :check!
|
||||||
|
|
||||||
|
def check!
|
||||||
|
# params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
|
||||||
|
case strip(type).to_i
|
||||||
|
when 1 then check_login(strip(value))
|
||||||
|
when 2 then check_mail(strip(value))
|
||||||
|
when 3 then check_phone(strip(value))
|
||||||
|
else raise("type值无效")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,27 @@
|
||||||
|
module Register
|
||||||
|
class Form < Register::BaseForm
|
||||||
|
# login 登陆方式,支持邮箱、登陆、手机号等
|
||||||
|
# namespace 用户空间地址
|
||||||
|
# type: 1:手机号注册;2:邮箱注册
|
||||||
|
attr_accessor :login, :namespace, :password, :code, :type
|
||||||
|
|
||||||
|
validates :login, :code, :password, :namespace, presence: true
|
||||||
|
validate :check!
|
||||||
|
|
||||||
|
def check!
|
||||||
|
Rails.logger.info "Register::Form params: code: #{code}; login: #{login}; namespace: #{namespace}; password: #{password}; type: #{type}"
|
||||||
|
db_verifi_code =
|
||||||
|
if type == 1
|
||||||
|
check_phone(login)
|
||||||
|
VerificationCode.where(phone: login, code: code, code_type: 1).last
|
||||||
|
elsif type == 0
|
||||||
|
check_mail(login)
|
||||||
|
VerificationCode.where(email: login, code: code, code_type: 8).last
|
||||||
|
end
|
||||||
|
|
||||||
|
check_login(namespace)
|
||||||
|
check_verifi_code(db_verifi_code, code)
|
||||||
|
check_password(password)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -463,5 +463,11 @@ module ApplicationHelper
|
||||||
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 1 手机类型;0 邮箱类型
|
||||||
|
# 注意新版的login是自动名生成的
|
||||||
|
def phone_mail_type value
|
||||||
|
value =~ /^1\d{10}$/ ? 1 : 0
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module CustomRegexp
|
module CustomRegexp
|
||||||
PHONE = /1\d{10}/
|
PHONE = /1\d{10}/
|
||||||
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
|
EMAIL = /\A[a-zA-Z0-9]+([._\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+\z/
|
||||||
|
LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
|
||||||
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
|
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
|
||||||
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
|
||||||
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
|
||||||
|
|
|
@ -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
|
|
@ -1,17 +1,11 @@
|
||||||
class UserMailer < ApplicationMailer
|
class UserMailer < ApplicationMailer
|
||||||
# 注意:这个地方一定要和你的邮箱服务域名一致
|
# 注意:这个地方一定要和你的邮箱服务域名一致
|
||||||
default from: 'educoder@trustie.org'
|
default from: 'notification@trustie.org'
|
||||||
|
|
||||||
# 用户注册验证码
|
# 用户注册验证码
|
||||||
def register_email(mail, code)
|
def register_email(mail, code)
|
||||||
@code = code
|
@code = code
|
||||||
mail(to: mail, subject: '验证你的电子邮件')
|
mail(to: mail, subject: 'Gitink | 注册验证码')
|
||||||
end
|
end
|
||||||
|
|
||||||
# 课堂讨论区的邮件通知
|
|
||||||
def course_message_email(mail, message_id)
|
|
||||||
@message = Message.find_by(id: message_id)
|
|
||||||
@course = @message&.board&.course
|
|
||||||
mail(to: mail, subject: '课堂发布了新的帖子') if @message.present? && @course.present?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,10 @@ class ReversedKeyword < ApplicationRecord
|
||||||
|
|
||||||
before_validation :set_identifier
|
before_validation :set_identifier
|
||||||
|
|
||||||
|
def self.check_exists?(identifier)
|
||||||
|
self.is_reversed(identifier).exists?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_identifier
|
def set_identifier
|
||||||
|
|
|
@ -15,6 +15,13 @@ class SystemNotification < ApplicationRecord
|
||||||
|
|
||||||
default_scope { order(created_at: :desc)}
|
default_scope { order(created_at: :desc)}
|
||||||
|
|
||||||
|
has_many :system_notification_histories
|
||||||
|
has_many :users, through: :system_notification_histories
|
||||||
|
|
||||||
scope :is_top, lambda { where(is_top: true) }
|
scope :is_top, lambda { where(is_top: true) }
|
||||||
|
|
||||||
|
def read_member?(user_id)
|
||||||
|
self.system_notification_histories.where(user_id: user_id).present? ? true : false
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: system_notification_histories
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# system_message_id :integer
|
||||||
|
# user_id :integer
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_system_notification_histories_on_system_message_id (system_message_id)
|
||||||
|
# index_system_notification_histories_on_user_id (user_id)
|
||||||
|
#
|
||||||
|
|
||||||
|
class SystemNotificationHistory < ApplicationRecord
|
||||||
|
|
||||||
|
belongs_to :system_notification
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
validates :system_notification_id, uniqueness: { scope: :user_id, message: '只能阅读一次'}
|
||||||
|
end
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -117,8 +117,6 @@ class User < Owner
|
||||||
enumerize :platform, in: [:forge, :educoder, :trustie, :military], default: :forge, scope: :shallow
|
enumerize :platform, in: [:forge, :educoder, :trustie, :military], default: :forge, scope: :shallow
|
||||||
|
|
||||||
belongs_to :laboratory, optional: true
|
belongs_to :laboratory, optional: true
|
||||||
has_many :composes, dependent: :destroy
|
|
||||||
has_many :compose_users, dependent: :destroy
|
|
||||||
has_one :user_extension, dependent: :destroy
|
has_one :user_extension, dependent: :destroy
|
||||||
has_many :open_users, dependent: :destroy
|
has_many :open_users, dependent: :destroy
|
||||||
has_one :wechat_open_user, class_name: 'OpenUsers::Wechat'
|
has_one :wechat_open_user, class_name: 'OpenUsers::Wechat'
|
||||||
|
@ -174,6 +172,9 @@ class User < Owner
|
||||||
|
|
||||||
has_one :user_template_message_setting, dependent: :destroy
|
has_one :user_template_message_setting, dependent: :destroy
|
||||||
|
|
||||||
|
has_many :system_notification_histories
|
||||||
|
has_many :system_notifications, through: :system_notification_histories
|
||||||
|
|
||||||
# Groups and active users
|
# Groups and active users
|
||||||
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
|
||||||
scope :like, lambda { |keywords|
|
scope :like, lambda { |keywords|
|
||||||
|
@ -440,6 +441,7 @@ class User < Owner
|
||||||
|
|
||||||
def activate!
|
def activate!
|
||||||
update_attribute(:status, STATUS_ACTIVE)
|
update_attribute(:status, STATUS_ACTIVE)
|
||||||
|
prohibit_gitea_user_login!(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def register!
|
def register!
|
||||||
|
@ -448,6 +450,12 @@ class User < Owner
|
||||||
|
|
||||||
def lock!
|
def lock!
|
||||||
update_attribute(:status, STATUS_LOCKED)
|
update_attribute(:status, STATUS_LOCKED)
|
||||||
|
prohibit_gitea_user_login!
|
||||||
|
end
|
||||||
|
|
||||||
|
def prohibit_gitea_user_login!(prohibit_login = true)
|
||||||
|
Gitea::User::UpdateInteractor.call(self.login,
|
||||||
|
{email: self.mail, prohibit_login: prohibit_login})
|
||||||
end
|
end
|
||||||
|
|
||||||
def need_edit_info!
|
def need_edit_info!
|
||||||
|
|
|
@ -11,20 +11,45 @@ class Projects::ListQuery < ApplicationQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def call
|
def call
|
||||||
q = params[:pinned].present? ? Project.pinned : Project
|
collection = Project.all
|
||||||
q = q.visible.by_name_or_identifier(params[:search])
|
collection = filter_projects(collection)
|
||||||
|
|
||||||
scope = q
|
|
||||||
.with_project_type(params[:project_type])
|
|
||||||
.with_project_category(params[:category_id])
|
|
||||||
.with_project_language(params[:language_id])
|
|
||||||
|
|
||||||
sort = params[:sort_by] || "updated_on"
|
sort = params[:sort_by] || "updated_on"
|
||||||
sort_direction = params[:sort_direction] || "desc"
|
sort_direction = params[:sort_direction] || "desc"
|
||||||
|
|
||||||
custom_sort(scope, sort, sort_direction)
|
custom_sort(collection, sort, sort_direction)
|
||||||
|
|
||||||
# scope = scope.reorder("projects.#{sort} #{sort_direction}")
|
# scope = scope.reorder("projects.#{sort} #{sort_direction}")
|
||||||
# scope
|
# scope
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def filter_projects(collection)
|
||||||
|
collection = by_pinned(collection)
|
||||||
|
collection = by_search(collection)
|
||||||
|
collection = by_project_type(collection)
|
||||||
|
collection = by_project_category(collection)
|
||||||
|
collection = by_project_language(collection)
|
||||||
|
collection
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_search(items)
|
||||||
|
items.visible.by_name_or_identifier(params[:search])
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_project_type(items)
|
||||||
|
items.with_project_type(params[:project_type])
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_project_category(items)
|
||||||
|
items.with_project_category(params[:category_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_project_language(items)
|
||||||
|
items.with_project_language(params[:language_id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def by_pinned(items)
|
||||||
|
(params[:pinned].present? && params[:category_id].present?) ? items.pinned : items
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,19 +15,13 @@ class Admins::UpdateUserService < ApplicationService
|
||||||
user.firstname = ''
|
user.firstname = ''
|
||||||
user.password = params[:password] if params[:password].present?
|
user.password = params[:password] if params[:password].present?
|
||||||
|
|
||||||
if params[:identity].to_s == 'student'
|
|
||||||
params[:technical_title] = nil
|
|
||||||
else
|
|
||||||
params[:student_id] = nil
|
|
||||||
end
|
|
||||||
user.user_extension.assign_attributes(user_extension_attributes)
|
user.user_extension.assign_attributes(user_extension_attributes)
|
||||||
|
|
||||||
|
old_login = user.login
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
user.save!
|
user.save!
|
||||||
user.user_extension.save!
|
user.user_extension.save!
|
||||||
user.update!(is_shixun_marker: true) if user.is_certification_teacher
|
update_gitea_user(old_login)
|
||||||
|
|
||||||
update_gitlab_password if params[:password].present?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
user
|
user
|
||||||
|
@ -36,7 +30,7 @@ class Admins::UpdateUserService < ApplicationService
|
||||||
private
|
private
|
||||||
|
|
||||||
def user_attributes
|
def user_attributes
|
||||||
params.slice(*%i[lastname nickname mail phone admin business is_test
|
params.slice(*%i[lastname nickname mail phone admin business is_test login
|
||||||
professional_certification authentication is_shixun_marker])
|
professional_certification authentication is_shixun_marker])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -44,10 +38,29 @@ class Admins::UpdateUserService < ApplicationService
|
||||||
params.slice(*%i[gender identity technical_title student_id location location_city school_id department_id])
|
params.slice(*%i[gender identity technical_title student_id location location_city school_id department_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_gitlab_password
|
def gitea_user_params
|
||||||
return if user.gid.blank?
|
hash = {
|
||||||
# 同步修改gitlab密码
|
password: params[:password].to_s.presence,
|
||||||
Gitlab.client.edit_user(user.gid, password: params[:password])
|
email: user.mail,
|
||||||
|
login_name: params[:login].to_s.presence,
|
||||||
|
admin: boolean_admin
|
||||||
|
}.compact
|
||||||
|
|
||||||
|
hash.delete_if {|_,v| v.to_s.strip == ''}
|
||||||
|
end
|
||||||
|
|
||||||
|
def boolean_admin
|
||||||
|
admin = params[:admin].to_s.presence
|
||||||
|
case admin
|
||||||
|
when "0" then false
|
||||||
|
when "1" then true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_gitea_user(old_login)
|
||||||
|
return if user.gitea_uid.blank?
|
||||||
|
|
||||||
|
Gitea::User::UpdateInteractor.call(old_login, gitea_user_params)
|
||||||
rescue Exception => ex
|
rescue Exception => ex
|
||||||
Util.logger_error(ex)
|
Util.logger_error(ex)
|
||||||
raise Error, '保存失败'
|
raise Error, '保存失败'
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -82,6 +82,8 @@ class Gitea::ClientService < ApplicationService
|
||||||
req.headers['Content-Type'] = 'application/json'
|
req.headers['Content-Type'] = 'application/json'
|
||||||
req.response :logger # 显示日志
|
req.response :logger # 显示日志
|
||||||
req.adapter Faraday.default_adapter
|
req.adapter Faraday.default_adapter
|
||||||
|
req.options.timeout = 100 # open/read timeout in seconds
|
||||||
|
req.options.open_timeout = 10 # connection open timeout in seconds
|
||||||
if token.blank?
|
if token.blank?
|
||||||
req.basic_auth(username, secret)
|
req.basic_auth(username, secret)
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
class Gitea::User::DeleteService < Gitea::ClientService
|
||||||
|
attr_reader :username
|
||||||
|
|
||||||
|
def initialize(username)
|
||||||
|
@username = username
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
response = delete(request_url, params)
|
||||||
|
|
||||||
|
render_status(response)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def token
|
||||||
|
{
|
||||||
|
username: Gitea.gitea_config[:access_key_id],
|
||||||
|
password: Gitea.gitea_config[:access_key_secret]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def request_url
|
||||||
|
"/admin/users/#{username}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def params
|
||||||
|
Hash.new.merge(token: token)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
|
@ -0,0 +1,58 @@
|
||||||
|
class Users::RegisterService < ApplicationService
|
||||||
|
def initialize(params)
|
||||||
|
@login = params[:login]
|
||||||
|
@namespace = params[:namespace]
|
||||||
|
@password = params[:password]
|
||||||
|
@code = params[:code]
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
code = strip(@code)
|
||||||
|
login = strip(@login)
|
||||||
|
namespace = strip(@namespace)
|
||||||
|
password = strip(@password)
|
||||||
|
|
||||||
|
Rails.logger.info "Users::RegisterService params: ##### #{params} "
|
||||||
|
|
||||||
|
email, phone =
|
||||||
|
if register_type == 1
|
||||||
|
phone_register(login, code)
|
||||||
|
elsif register_type == 0
|
||||||
|
mail_register(login, code)
|
||||||
|
end
|
||||||
|
|
||||||
|
user = User.new(admin: false, login: namespace, mail: email, phone: phone, type: "User")
|
||||||
|
user.password = password
|
||||||
|
user.activate # 现在因为是验证码,所以在注册的时候就可以激活
|
||||||
|
|
||||||
|
user
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# 手机注册
|
||||||
|
def phone_register(login, code)
|
||||||
|
Rails.logger.info("start register by phone: phone is #{login}")
|
||||||
|
email = nil
|
||||||
|
phone = login
|
||||||
|
|
||||||
|
[email, phone]
|
||||||
|
end
|
||||||
|
|
||||||
|
# 邮箱注册
|
||||||
|
def mail_register(login, code)
|
||||||
|
Rails.logger.info("start register by email: email is #{login}")
|
||||||
|
email = login
|
||||||
|
phone = nil
|
||||||
|
|
||||||
|
[email, phone]
|
||||||
|
end
|
||||||
|
|
||||||
|
def register_type
|
||||||
|
phone_mail_type(@login)
|
||||||
|
end
|
||||||
|
|
||||||
|
def phone_mail_type value
|
||||||
|
value =~ /^1\d{10}$/ ? 1 : 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -31,17 +31,30 @@
|
||||||
|
|
||||||
<li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li>
|
<li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li>
|
||||||
<li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li>
|
<li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li>
|
||||||
|
<li>
|
||||||
<!-- <li>
|
<%= sidebar_item_group('#setting-index', '首页配置', icon: 'file') do %>
|
||||||
|
<li><%= sidebar_item(admins_topic_banners_path, 'banner管理', icon: 'image', controller: 'admins-topic-banners') %></li>
|
||||||
|
<li><%= sidebar_item(admins_topic_cards_path, '卡片管理', icon: 'archive', controller: 'admins-topic-cards') %></li>
|
||||||
|
<li><%= sidebar_item(admins_topic_activity_forums_path, '平台动态管理', icon: 'bell', controller: 'admins-topic-activity_forums') %></li>
|
||||||
|
<li><%= sidebar_item(admins_topic_excellent_projects_path, '优秀仓库管理', icon: 'git', controller: 'admins-topic-excellent_projects') %></li>
|
||||||
|
<li><%= sidebar_item(admins_topic_pinned_forums_path, '精选文章管理', icon: 'edit', controller: 'admins-topic-pinned_forums') %></li>
|
||||||
|
<li><%= sidebar_item(admins_topic_experience_forums_path, '经验分享管理', icon: 'edit', controller: 'admins-topic-experience_forums') %></li>
|
||||||
|
<li><%= sidebar_item(admins_topic_cooperators_path, '合作伙伴管理', icon: 'user', controller: 'admins-topic-cooperators') %></li>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
|
<%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
|
||||||
|
<!-- >
|
||||||
<li><%= sidebar_item(edit_admins_about_path, '关于我们', icon: 'smile-o', controller: 'admins-abouts') %></li>
|
<li><%= sidebar_item(edit_admins_about_path, '关于我们', icon: 'smile-o', controller: 'admins-abouts') %></li>
|
||||||
<li><%= sidebar_item(edit_admins_contact_us_path, '联系我们', icon: 'commenting-o', controller: 'admins-contact_us') %></li>
|
<li><%= sidebar_item(edit_admins_contact_us_path, '联系我们', icon: 'commenting-o', controller: 'admins-contact_us') %></li>
|
||||||
<li><%= sidebar_item(admins_cooperatives_path, '合作伙伴', icon: 'handshake-o', controller: 'admins-cooperatives') %></li>
|
<li><%= sidebar_item(admins_cooperatives_path, '合作伙伴', icon: 'handshake-o', controller: 'admins-cooperatives') %></li>
|
||||||
<li><%= sidebar_item(edit_admins_agreement_path, '服务协议', icon: 'file-text-o', controller: 'admins-agreements') %></li>
|
<li><%= sidebar_item(edit_admins_agreement_path, '服务协议', icon: 'file-text-o', controller: 'admins-agreements') %></li>
|
||||||
<li><%= sidebar_item(edit_admins_help_center_path, '帮助中心', icon: 'question-circle-o', controller: 'admins-help_centers') %></li>
|
<li><%= sidebar_item(edit_admins_help_center_path, '帮助中心', icon: 'question-circle-o', controller: 'admins-help_centers') %></li>
|
||||||
|
-->
|
||||||
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li>
|
<li><%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</li> -->
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<%= sidebar_item_group('#setting-system', '系统配置', icon: 'wrench') do %>
|
<%= sidebar_item_group('#setting-system', '系统配置', icon: 'wrench') do %>
|
||||||
<li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %></li>
|
<li><%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %></li>
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<div class="modal fade activity-forum-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @activity_forum, url: {controller: "topic/activity_forums", action: "#{type}"} do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
跳转地址 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :url,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
帖子ID <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :uuid,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</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>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">跳转地址</th>
|
||||||
|
<th width="10%">帖子ID</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if activity_forums.present? %>
|
||||||
|
<% activity_forums.each_with_index do |activity_forum, index| %>
|
||||||
|
<tr class="activity-forum-item-<%= activity_forum.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= activity_forum.title %></td>
|
||||||
|
<td><%= activity_forum.url %></td>
|
||||||
|
<td><%= activity_forum.uuid %></td>
|
||||||
|
<td><%= activity_forum.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: activity_forums } %>
|
|
@ -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');
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('平台动态管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_activity_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container activity-forum-list-container">
|
||||||
|
<%= render partial: 'admins/topic/activity_forums/list', locals: { activity_forums: @activity_forums } %>
|
||||||
|
</div>
|
||||||
|
<div id="activity-forum-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.activity-forum-list-container').html("<%= j( render partial: 'admins/topic/activity_forums/list', locals: { activity_forums: @activity_forums } ) %>");
|
|
@ -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');
|
|
@ -0,0 +1,45 @@
|
||||||
|
<div class="modal fade banner-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @banner, url: {controller: "topic/banners", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</div>
|
||||||
|
<div class="logo-item">
|
||||||
|
<% logo_img = @banner.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</div>
|
||||||
|
<div>格式:PNG、JPG</div>
|
||||||
|
<div>尺寸:高度38px以内,宽等比例缩放</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>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">图片</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if banners.present? %>
|
||||||
|
<% banners.each_with_index do |banner, index| %>
|
||||||
|
<tr class="banner-item-<%= banner.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= banner.title %></td>
|
||||||
|
<td><img style="width:150px" src="<%= banner.image %>" /></td>
|
||||||
|
<td><%= banner.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: banners } %>
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('卡片管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_banner_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container banner-list-container">
|
||||||
|
<%= render partial: 'admins/topic/banners/list', locals: { banners: @banners } %>
|
||||||
|
</div>
|
||||||
|
<div id="banner-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.banner-list-container').html("<%= j( render partial: 'admins/topic/banners/list', locals: { banners: @banners } ) %>");
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,38 @@
|
||||||
|
<div class="modal fade card-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @card, url: {controller: "topic/cards", action: "#{type}"} do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
跳转地址 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :url,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</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>
|
|
@ -0,0 +1,31 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">跳转地址</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if cards.present? %>
|
||||||
|
<% cards.each_with_index do |card, index| %>
|
||||||
|
<tr class="card-item-<%= card.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= card.title %></td>
|
||||||
|
<td><%= card.url %></td>
|
||||||
|
<td><%= card.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: cards } %>
|
|
@ -0,0 +1,2 @@
|
||||||
|
$("#card-modals").html("<%= j render(partial: 'admins/topic/cards/form_modal', locals: {type: 'update'}) %>")
|
||||||
|
$(".card-change-modal").modal('show');
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('卡片管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_card_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container card-list-container">
|
||||||
|
<%= render partial: 'admins/topic/cards/list', locals: { cards: @cards } %>
|
||||||
|
</div>
|
||||||
|
<div id="card-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.card-list-container').html("<%= j( render partial: 'admins/topic/cards/list', locals: { cards: @cards } ) %>");
|
|
@ -0,0 +1,2 @@
|
||||||
|
$("#card-modals").html("<%= j render(partial: 'admins/topic/cards/form_modal', locals: {type: 'create'}) %>")
|
||||||
|
$(".card-change-modal").modal('show');
|
|
@ -0,0 +1,51 @@
|
||||||
|
<div class="modal fade cooperator-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @cooperator, url: {controller: "topic/cooperators", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
跳转地址 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :url,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</div>
|
||||||
|
<div class="logo-item">
|
||||||
|
<% logo_img = @cooperator.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</div>
|
||||||
|
<div>格式:PNG、JPG</div>
|
||||||
|
<div>尺寸:高度38px以内,宽等比例缩放</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>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">跳转地址</th>
|
||||||
|
<th width="20%">图片</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if cooperators.present? %>
|
||||||
|
<% cooperators.each_with_index do |cooperator, index| %>
|
||||||
|
<tr class="cooperator-item-<%= cooperator.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= cooperator.title %></td>
|
||||||
|
<td><%= cooperator.url %></td>
|
||||||
|
<td><img style="width:150px" src="<%= cooperator.image %>" /></td>
|
||||||
|
<td><%= cooperator.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: cooperators } %>
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('卡片管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_cooperator_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container cooperator-list-container">
|
||||||
|
<%= render partial: 'admins/topic/cooperators/list', locals: { cooperators: @cooperators } %>
|
||||||
|
</div>
|
||||||
|
<div id="cooperator-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.cooperator-list-container').html("<%= j( render partial: 'admins/topic/cooperators/list', locals: { cooperators: @cooperators } ) %>");
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,44 @@
|
||||||
|
<div class="modal fade excellent-project-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @excellent_project, url: {controller: "topic/excellent_projects", action: "#{type}"} do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
跳转地址 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :url,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
项目ID <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :uuid,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</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>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">跳转地址</th>
|
||||||
|
<th width="10%">项目ID</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if excellent_projects.present? %>
|
||||||
|
<% excellent_projects.each_with_index do |excellent_project, index| %>
|
||||||
|
<tr class="excellent-project-item-<%= excellent_project.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= excellent_project.title %></td>
|
||||||
|
<td><%= excellent_project.url %></td>
|
||||||
|
<td><%= excellent_project.uuid %></td>
|
||||||
|
<td><%= excellent_project.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: excellent_projects } %>
|
|
@ -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');
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('优秀仓库管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_excellent_project_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container excellent-project-list-container">
|
||||||
|
<%= render partial: 'admins/topic/excellent_projects/list', locals: { excellent_projects: @excellent_projects } %>
|
||||||
|
</div>
|
||||||
|
<div id="excellent-project-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.excellent-project-list-container').html("<%= j( render partial: 'admins/topic/excellent_projects/list', locals: { excellent_projects: @excellent_projects } ) %>");
|
|
@ -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');
|
|
@ -0,0 +1,44 @@
|
||||||
|
<div class="modal fade experience-forum-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @experience_forum, url: {controller: "topic/experience_forums", action: "#{type}"} do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
跳转地址 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :url,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
帖子ID <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :uuid,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</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>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">跳转地址</th>
|
||||||
|
<th width="10%">帖子ID</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if experience_forums.present? %>
|
||||||
|
<% experience_forums.each_with_index do |experience_forum, index| %>
|
||||||
|
<tr class="experience-forum-item-<%= experience_forum.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= experience_forum.title %></td>
|
||||||
|
<td><%= experience_forum.url %></td>
|
||||||
|
<td><%= experience_forum.uuid %></td>
|
||||||
|
<td><%= experience_forum.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: experience_forums } %>
|
|
@ -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');
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('经验分享管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_experience_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container experience-forum-list-container">
|
||||||
|
<%= render partial: 'admins/topic/experience_forums/list', locals: { experience_forums: @experience_forums } %>
|
||||||
|
</div>
|
||||||
|
<div id="experience-forum-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.experience-forum-list-container').html("<%= j( render partial: 'admins/topic/experience_forums/list', locals: { experience_forums: @experience_forums } ) %>");
|
|
@ -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');
|
|
@ -0,0 +1,44 @@
|
||||||
|
<div class="modal fade pinned-forum-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">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<%= form_for @pinned_forum, url: {controller: "topic/pinned_forums", action: "#{type}"} do |p| %>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
标题 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :title,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
跳转地址 <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.text_field :url,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
帖子ID <span class="ml10 color-orange mr20">*</span>
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :uuid,class: "form-control input-lg",required: true%>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>
|
||||||
|
排序等级
|
||||||
|
</label>
|
||||||
|
<%= p.number_field :order_index, class: "form-control",placeholder: ""%>
|
||||||
|
</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>
|
|
@ -0,0 +1,33 @@
|
||||||
|
<table class="table table-hover text-center subject-list-table">
|
||||||
|
<thead class="thead-light">
|
||||||
|
<tr>
|
||||||
|
<th width="5%">序号</th>
|
||||||
|
<th width="20%">标题</th>
|
||||||
|
<th width="20%">跳转地址</th>
|
||||||
|
<th width="10%">帖子ID</th>
|
||||||
|
<th width="20%">排序等级</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% if pinned_forums.present? %>
|
||||||
|
<% pinned_forums.each_with_index do |pinned_forum, index| %>
|
||||||
|
<tr class="pinned-forum-item-<%= pinned_forum.id %>">
|
||||||
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
|
<td><%= pinned_forum.title %></td>
|
||||||
|
<td><%= pinned_forum.url %></td>
|
||||||
|
<td><%= pinned_forum.uuid %></td>
|
||||||
|
<td><%= pinned_forum.order_index %></td>
|
||||||
|
<td class="action-container">
|
||||||
|
<%= 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" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
<% else %>
|
||||||
|
<%= render 'admins/shared/no_data_for_table' %>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= render partial: 'admins/shared/paginate', locals: { objects: pinned_forums } %>
|
|
@ -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');
|
|
@ -0,0 +1,18 @@
|
||||||
|
<% define_admin_breadcrumbs do %>
|
||||||
|
<% add_admin_breadcrumb('精选文章管理') %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div class="box search-form-container project-list-form">
|
||||||
|
<%= 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': '搜索中...') %>
|
||||||
|
<input type="reset" class="btn btn-secondary clear-btn" value="清空"/>
|
||||||
|
<% end %>
|
||||||
|
<%= link_to "新增", new_admins_topic_pinned_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box admin-list-container pinned-forum-list-container">
|
||||||
|
<%= render partial: 'admins/topic/pinned_forums/list', locals: { pinned_forums: @pinned_forums } %>
|
||||||
|
</div>
|
||||||
|
<div id="pinned-forum-modals">
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
$('.pinned-forum-list-container').html("<%= j( render partial: 'admins/topic/pinned_forums/list', locals: { pinned_forums: @pinned_forums } ) %>");
|
|
@ -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');
|
|
@ -7,8 +7,8 @@
|
||||||
|
|
||||||
<div class="box user-edit-container">
|
<div class="box user-edit-container">
|
||||||
<div class="user-info mb-4 row">
|
<div class="user-info mb-4 row">
|
||||||
<%= link_to "/users/#{@user.login}", class: 'user-info-avatar col-md-1', target: '_blank', data: { toggle: 'tooltip', title: '个人中心' } do %>
|
<%= link_to "/#{@user.login}", class: 'user-info-avatar col-md-1', target: '_blank', data: { toggle: 'tooltip', title: '个人中心' } do %>
|
||||||
<img src="/images/<%= url_to_avatar(@user) %>" class="rounded-circle" width="80" height="80" />
|
<img src="/<%= url_to_avatar(@user) %>" class="rounded-circle" width="80" height="80" />
|
||||||
<% end %>
|
<% end %>
|
||||||
<div class="d-flex flex-column justify-content-between col-md-3 user-info-content">
|
<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="user-info-name flex"><%= @user.real_name %> | <%= @user.id %> | <%= @user.login %></div>
|
||||||
|
@ -50,6 +50,10 @@
|
||||||
|
|
||||||
<div><h6>基本信息</h6></div>
|
<div><h6>基本信息</h6></div>
|
||||||
<div class="form-group px-2">
|
<div class="form-group px-2">
|
||||||
|
<div class="form-row">
|
||||||
|
<%= f.input :login, label: '登录名', wrapper_html: { class: 'col-md-3' }, input_html: { readonly: true, class: 'col-md-11', value: @user.login } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<%= f.input :lastname, label: '姓名', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-md-11', value: @user.only_real_name } %>
|
<%= f.input :lastname, label: '姓名', wrapper_html: { class: 'col-md-3' }, input_html: { class: 'col-md-11', value: @user.only_real_name } %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,7 +113,6 @@
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<%= f.input :professional_certification, as: :boolean, label: '职业认证', checked_value: 1, unchecked_value: 0 %>
|
<%= f.input :professional_certification, as: :boolean, label: '职业认证', checked_value: 1, unchecked_value: 0 %>
|
||||||
<%= f.input :authentication, as: :boolean, label: '实名认证', wrapper_html: { class: 'ml-3' }, checked_value: 1, unchecked_value: 0 %>
|
<%= f.input :authentication, as: :boolean, label: '实名认证', wrapper_html: { class: 'ml-3' }, checked_value: 1, unchecked_value: 0 %>
|
||||||
<%= f.input :is_shixun_marker, as: :boolean, label: '实训制作', wrapper_html: { class: 'ml-3' }, checked_value: 1, unchecked_value: 0 %>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<tr class="user-item-<%= user.id %>">
|
<tr class="user-item-<%= user.id %>">
|
||||||
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
<td><%= list_index_no((params[:page] || 1).to_i, index) %></td>
|
||||||
<td class="text-left">
|
<td class="text-left">
|
||||||
<%= link_to "/users/#{user.login}", target: '_blank' do %>
|
<%= link_to "/#{user.login}", target: '_blank' do %>
|
||||||
<%= overflow_hidden_span user.real_name, width: 100 %>
|
<%= overflow_hidden_span user.real_name, width: 100 %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</td>
|
</td>
|
||||||
|
@ -44,7 +44,6 @@
|
||||||
<div class="d-inline">
|
<div class="d-inline">
|
||||||
<%= javascript_void_link('更多', class: 'action dropdown-toggle', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false) %>
|
<%= javascript_void_link('更多', class: 'action dropdown-toggle', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false) %>
|
||||||
<div class="dropdown-menu more-action-dropdown">
|
<div class="dropdown-menu more-action-dropdown">
|
||||||
<%= javascript_void_link('奖励', class: 'dropdown-item reward-grade-action', data: { toggle: 'modal', target: '.admin-users-reward-grade-modal', id: user.id }) %>
|
|
||||||
|
|
||||||
<%= javascript_void_link '恢复禁密账号', class: 'dropdown-item reset-login-times-action', data: { id: user.id } %>
|
<%= javascript_void_link '恢复禁密账号', class: 'dropdown-item reset-login-times-action', data: { id: user.id } %>
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ json.setting do
|
||||||
if @top_system_notification.present?
|
if @top_system_notification.present?
|
||||||
json.system_notification do
|
json.system_notification do
|
||||||
json.(@top_system_notification, :id, :subject, :sub_subject, :content)
|
json.(@top_system_notification, :id, :subject, :sub_subject, :content)
|
||||||
|
json.is_read @top_system_notification.read_member?(current_user&.id)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
json.system_notification nil
|
json.system_notification nil
|
||||||
|
|
|
@ -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"]
|
|
@ -0,0 +1 @@
|
||||||
|
json.(banner, :id, :title, :image)
|
|
@ -0,0 +1 @@
|
||||||
|
json.(card, :id, :title, :url)
|
|
@ -0,0 +1 @@
|
||||||
|
json.(cooperator, :id, :title, :image, :url)
|
|
@ -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
|
|
@ -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"]
|
|
@ -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"]
|
|
@ -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
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue