diff --git a/api_document.md b/api_document.md
index 8a579f8e7..a43147bb2 100644
--- a/api_document.md
+++ b/api_document.md
@@ -51,6 +51,51 @@ http://localhost:3000/api/accounts/remote_register | jq
|-- 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
{
diff --git a/app/assets/images/logo.png b/app/assets/images/logo.png
index 436d23490..72505d8a2 100644
Binary files a/app/assets/images/logo.png and b/app/assets/images/logo.png differ
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 18fa65fbe..b8783c44e 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -1,4 +1,5 @@
class AccountsController < ApplicationController
+ include ApplicationHelper
#skip_before_action :check_account, :only => [:logout]
@@ -9,7 +10,7 @@ class AccountsController < ApplicationController
# 其他平台同步注册的用户
def remote_register
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+/, "")
password = params[:password]
platform = (params[:platform] || 'forge')&.gsub(/\s+/, "")
@@ -109,67 +110,46 @@ class AccountsController < ApplicationController
# 用户注册
# 注意:用户注册需要兼顾本地版,本地版是不需要验证码及激活码以及使用授权的,注册完成即可使用
# params[:login] 邮箱或者手机号
+ # params[:namespace] 登录名
# params[:code] 验证码
# code_type 1:注册手机验证码 8:邮箱注册验证码
- # 本地forge注册入口
+ # 本地forge注册入口需要重新更改逻辑
def register
+ # type只可能是1或者8
+ user = nil
begin
- # 查询验证码是否正确;type只可能是1或者8
- type = phone_mail_type(params[:login].strip)
- # code = params[:code].strip
+ Register::Form.new(register_params).validate!
- if type == 1
- uid_logger("start register by phone: type is #{type}")
- 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
+ user = Users::RegisterService.call(register_params)
+ password = register_params[:password].strip
- code = generate_identifier User, 8, pre
- login = pre + code
-
- 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]})
+ # gitea用户注册, email, username, password
+ interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
if interactor.success?
gitea_user = interactor.result
- result = Gitea::User::GenerateTokenService.new(login, params[:password]).call
- @user.gitea_token = result['sha1']
- @user.gitea_uid = gitea_user[:body]['id']
- if @user.save!
- # set user for admin role
- if @user.admin?
- sync_params = { email: @user.mail, admin: true }
- Gitea::User::UpdateInteractor.call(@user.login, sync_params)
- end
- UserExtension.create!(user_id: @user.id)
- successful_authentication(@user)
- normal_status("注册成功")
+ result = Gitea::User::GenerateTokenService.call(user.login, password)
+ user.gitea_token = result['sha1']
+ user.gitea_uid = gitea_user[:body]['id']
+ if user.save!
+ UserExtension.create!(user_id: user.id)
+ successful_authentication(user)
+ render_ok
end
else
tip_exception(-1, interactor.error)
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
+ Gitea::User::DeleteService.call(user.login) unless user.nil?
uid_logger_error(e.message)
tip_exception(-1, e.message)
end
@@ -304,7 +284,7 @@ class AccountsController < ApplicationController
# 发送验证码
# params[:login] 手机号或者邮箱号
- # params[:type]为事件通知类型 1:用户注册注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
+ # params[:type]为事件通知类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验收手机号有效 # 如果有新的继续后面加
# 发送验证码:send_type 1:注册手机验证码 2:找回密码手机验证码 3:找回密码邮箱验证码 4:绑定手机 5:绑定邮箱
# 6:手机验证码登录 7:邮箱验证码登录 8:邮箱注册验证码 9: 验收手机号有效
def get_verification_code
@@ -318,19 +298,22 @@ class AccountsController < ApplicationController
sign = Digest::MD5.hexdigest("#{OPENKEY}#{value}")
tip_exception(501, "请求不合理") if sign != params[:smscode]
+ logger.info "########### 验证码:#{verification_code}"
logger.info("########get_verification_code: login_type: #{login_type}, send_type:#{send_type}, ")
# 记录验证码
check_verification_code(verification_code, send_type, value)
- sucess_status
+ render_ok
end
- # 1 手机类型;0 邮箱类型
- # 注意新版的login是自动名生成的
- def phone_mail_type value
- value =~ /^1\d{10}$/ ? 1 : 0
+ # check user's login or email or phone is used
+ # params[:value] 手机号或者邮箱号或者登录名
+ # params[:type] 为事件类型 1:登录名(login) 2:email(邮箱) 3:phone(手机号)
+ def check
+ Register::CheckColumnsForm.new(check_params).validate!
+ render_ok
end
-
+
private
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
@@ -376,4 +359,13 @@ class AccountsController < ApplicationController
def account_params
params.require(:account).permit(:login, :password)
end
+
+ def check_params
+ params.permit(:type, :value)
+ end
+
+ def register_params
+ params.permit(:login, :namespace, :password, :code)
+ end
+
end
diff --git a/app/controllers/admins/system_notifications_controller.rb b/app/controllers/admins/system_notifications_controller.rb
index 0dc7dd2a2..e2081f1a2 100644
--- a/app/controllers/admins/system_notifications_controller.rb
+++ b/app/controllers/admins/system_notifications_controller.rb
@@ -10,6 +10,10 @@ class Admins::SystemNotificationsController < Admins::BaseController
@notifications = paginate(notifications)
end
+ def history
+ @users = @notification.users
+ end
+
def new
@notification = SystemNotification.new
end
diff --git a/app/controllers/admins/topic/activity_forums_controller.rb b/app/controllers/admins/topic/activity_forums_controller.rb
new file mode 100644
index 000000000..b027dc003
--- /dev/null
+++ b/app/controllers/admins/topic/activity_forums_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::ActivityForumsController < Admins::Topic::BaseController
+ before_action :find_activity_forum, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::ActivityForum.ransack(title_cont: params[:search])
+ activity_forums = q.result(distinct: true)
+ @activity_forums = paginate(activity_forums)
+ end
+
+ def new
+ @activity_forum = ::Topic::ActivityForum.new
+ end
+
+ def create
+ @activity_forum = ::Topic::ActivityForum.new(activity_forum_params)
+ if @activity_forum.save
+ redirect_to admins_topic_activity_forums_path
+ flash[:success] = "新增平台动态成功"
+ else
+ redirect_to admins_topic_activity_forums_path
+ flash[:danger] = "新增平台动态失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @activity_forum.attributes = activity_forum_params
+ if @activity_forum.save
+ redirect_to admins_topic_activity_forums_path
+ flash[:success] = "更新平台动态成功"
+ else
+ redirect_to admins_topic_activity_forums_path
+ flash[:danger] = "更新平台动态失败"
+ end
+ end
+
+ def destroy
+ if @activity_forum.destroy
+ redirect_to admins_topic_activity_forums_path
+ flash[:success] = "删除平台动态成功"
+ else
+ redirect_to admins_topic_activity_forums_path
+ flash[:danger] = "删除平台动态失败"
+ end
+ end
+
+ private
+ def find_activity_forum
+ @activity_forum = ::Topic::ActivityForum.find_by_id(params[:id])
+ end
+
+ def activity_forum_params
+ params.require(:topic_activity_forum).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/banners_controller.rb b/app/controllers/admins/topic/banners_controller.rb
new file mode 100644
index 000000000..359845806
--- /dev/null
+++ b/app/controllers/admins/topic/banners_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::BannersController < Admins::Topic::BaseController
+ before_action :find_banner, only: [:edit, :update, :destroy]
+
+ def index
+ @banners = paginate(::Topic::Banner)
+ end
+
+ def new
+ @banner = ::Topic::Banner.new
+ end
+
+ def create
+ @banner = ::Topic::Banner.new(banner_params)
+ if @banner.save
+ save_image_file(params[:image], @banner)
+ redirect_to admins_topic_banners_path
+ flash[:success] = "新增banner成功"
+ else
+ redirect_to admins_topic_banners_path
+ flash[:danger] = "新增banner失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @banner.attributes = banner_params
+ if @banner.save
+ save_image_file(params[:image], @banner)
+ redirect_to admins_topic_banners_path
+ flash[:success] = "更新banner成功"
+ else
+ redirect_to admins_topic_banners_path
+ flash[:danger] = "更新banner失败"
+ end
+ end
+
+ def destroy
+ if @banner.destroy
+ redirect_to admins_topic_banners_path
+ flash[:success] = "删除banner成功"
+ else
+ redirect_to admins_topic_banners_path
+ flash[:danger] = "删除banner失败"
+ end
+ end
+
+ private
+ def find_banner
+ @banner = ::Topic::Banner.find_by_id(params[:id])
+ end
+
+ def banner_params
+ params.require(:topic_banner).permit(:title, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/base_controller.rb b/app/controllers/admins/topic/base_controller.rb
new file mode 100644
index 000000000..1360232c8
--- /dev/null
+++ b/app/controllers/admins/topic/base_controller.rb
@@ -0,0 +1,11 @@
+class Admins::Topic::BaseController < Admins::BaseController
+
+ protected
+ def save_image_file(file, topic)
+ return unless file.present? && file.is_a?(ActionDispatch::Http::UploadedFile)
+
+ file_path = Util::FileManage.source_disk_filename(topic, 'image')
+ File.delete(file_path) if File.exist?(file_path) # 删除之前的文件
+ Util.write_file(file, file_path)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/cards_controller.rb b/app/controllers/admins/topic/cards_controller.rb
new file mode 100644
index 000000000..732f17e5b
--- /dev/null
+++ b/app/controllers/admins/topic/cards_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::CardsController < Admins::Topic::BaseController
+ before_action :find_card, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::Card.ransack(title_cont: params[:search])
+ cards = q.result(distinct: true)
+ @cards = paginate(cards)
+ end
+
+ def new
+ @card = ::Topic::Card.new
+ end
+
+ def create
+ @card = ::Topic::Card.new(card_params)
+ if @card.save
+ redirect_to admins_topic_cards_path
+ flash[:success] = "新增合作单位成功"
+ else
+ redirect_to admins_topic_cards_path
+ flash[:danger] = "新增合作单位失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @card.attributes = card_params
+ if @card.save
+ redirect_to admins_topic_cards_path
+ flash[:success] = "更新合作单位成功"
+ else
+ redirect_to admins_topic_cards_path
+ flash[:danger] = "更新合作单位失败"
+ end
+ end
+
+ def destroy
+ if @card.destroy
+ redirect_to admins_topic_cards_path
+ flash[:success] = "删除合作单位成功"
+ else
+ redirect_to admins_topic_cards_path
+ flash[:danger] = "删除合作单位失败"
+ end
+ end
+
+ private
+ def find_card
+ @card = ::Topic::Card.find_by_id(params[:id])
+ end
+
+ def card_params
+ params.require(:topic_card).permit(:title, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/cooperators_controller.rb b/app/controllers/admins/topic/cooperators_controller.rb
new file mode 100644
index 000000000..a1a700cbc
--- /dev/null
+++ b/app/controllers/admins/topic/cooperators_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::CooperatorsController < Admins::Topic::BaseController
+ before_action :find_cooperator, only: [:edit, :update, :destroy]
+
+ def index
+ @cooperators = paginate(::Topic::Cooperator)
+ end
+
+ def new
+ @cooperator = ::Topic::Cooperator.new
+ end
+
+ def create
+ @cooperator = ::Topic::Cooperator.new(cooperator_params)
+ if @cooperator.save
+ save_image_file(params[:image], @cooperator)
+ redirect_to admins_topic_cooperators_path
+ flash[:success] = "新增合作单位成功"
+ else
+ redirect_to admins_topic_cooperators_path
+ flash[:danger] = "新增合作单位失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @cooperator.attributes = cooperator_params
+ if @cooperator.save
+ save_image_file(params[:image], @cooperator)
+ redirect_to admins_topic_cooperators_path
+ flash[:success] = "更新合作单位成功"
+ else
+ redirect_to admins_topic_cooperators_path
+ flash[:danger] = "更新合作单位失败"
+ end
+ end
+
+ def destroy
+ if @cooperator.destroy
+ redirect_to admins_topic_cooperators_path
+ flash[:success] = "删除合作单位成功"
+ else
+ redirect_to admins_topic_cooperators_path
+ flash[:danger] = "删除合作单位失败"
+ end
+ end
+
+ private
+ def find_cooperator
+ @cooperator = ::Topic::Cooperator.find_by_id(params[:id])
+ end
+
+ def cooperator_params
+ params.require(:topic_cooperator).permit(:title, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/excellent_projects_controller.rb b/app/controllers/admins/topic/excellent_projects_controller.rb
new file mode 100644
index 000000000..b60dac54c
--- /dev/null
+++ b/app/controllers/admins/topic/excellent_projects_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::ExcellentProjectsController < Admins::Topic::BaseController
+ before_action :find_excellent_project, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::ExcellentProject.ransack(title_cont: params[:search])
+ excellent_projects = q.result(distinct: true)
+ @excellent_projects = paginate(excellent_projects)
+ end
+
+ def new
+ @excellent_project = ::Topic::ExcellentProject.new
+ end
+
+ def create
+ @excellent_project = ::Topic::ExcellentProject.new(excellent_project_params)
+ if @excellent_project.save
+ redirect_to admins_topic_excellent_projects_path
+ flash[:success] = "新增优秀仓库成功"
+ else
+ redirect_to admins_topic_excellent_projects_path
+ flash[:danger] = "新增优秀仓库失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @excellent_project.attributes = excellent_project_params
+ if @excellent_project.save
+ redirect_to admins_topic_excellent_projects_path
+ flash[:success] = "更新优秀仓库成功"
+ else
+ redirect_to admins_topic_excellent_projects_path
+ flash[:danger] = "更新优秀仓库失败"
+ end
+ end
+
+ def destroy
+ if @excellent_project.destroy
+ redirect_to admins_topic_excellent_projects_path
+ flash[:success] = "删除优秀仓库成功"
+ else
+ redirect_to admins_topic_excellent_projects_path
+ flash[:danger] = "删除优秀仓库失败"
+ end
+ end
+
+ private
+ def find_excellent_project
+ @excellent_project = ::Topic::ExcellentProject.find_by_id(params[:id])
+ end
+
+ def excellent_project_params
+ params.require(:topic_excellent_project).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/experience_forums_controller.rb b/app/controllers/admins/topic/experience_forums_controller.rb
new file mode 100644
index 000000000..420670c1b
--- /dev/null
+++ b/app/controllers/admins/topic/experience_forums_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::ExperienceForumsController < Admins::Topic::BaseController
+ before_action :find_experience_forum, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::ExperienceForum.ransack(title_cont: params[:search])
+ experience_forums = q.result(distinct: true)
+ @experience_forums = paginate(experience_forums)
+ end
+
+ def new
+ @experience_forum = ::Topic::ExperienceForum.new
+ end
+
+ def create
+ @experience_forum = ::Topic::ExperienceForum.new(experience_forum_params)
+ if @experience_forum.save
+ redirect_to admins_topic_experience_forums_path
+ flash[:success] = "新增经验分享成功"
+ else
+ redirect_to admins_topic_experience_forums_path
+ flash[:danger] = "新增经验分享失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @experience_forum.attributes = experience_forum_params
+ if @experience_forum.save
+ redirect_to admins_topic_experience_forums_path
+ flash[:success] = "更新经验分享成功"
+ else
+ redirect_to admins_topic_experience_forums_path
+ flash[:danger] = "更新经验分享失败"
+ end
+ end
+
+ def destroy
+ if @experience_forum.destroy
+ redirect_to admins_topic_experience_forums_path
+ flash[:success] = "删除经验分享成功"
+ else
+ redirect_to admins_topic_experience_forums_path
+ flash[:danger] = "删除经验分享失败"
+ end
+ end
+
+ private
+ def find_experience_forum
+ @experience_forum = ::Topic::ExperienceForum.find_by_id(params[:id])
+ end
+
+ def experience_forum_params
+ params.require(:topic_experience_forum).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/topic/pinned_forums_controller.rb b/app/controllers/admins/topic/pinned_forums_controller.rb
new file mode 100644
index 000000000..ac5bf69a7
--- /dev/null
+++ b/app/controllers/admins/topic/pinned_forums_controller.rb
@@ -0,0 +1,57 @@
+class Admins::Topic::PinnedForumsController < Admins::Topic::BaseController
+ before_action :find_pinned_forum, only: [:edit, :update, :destroy]
+
+ def index
+ q = ::Topic::PinnedForum.ransack(title_cont: params[:search])
+ pinned_forums = q.result(distinct: true)
+ @pinned_forums = paginate(pinned_forums)
+ end
+
+ def new
+ @pinned_forum = ::Topic::PinnedForum.new
+ end
+
+ def create
+ @pinned_forum = ::Topic::PinnedForum.new(pinned_forum_params)
+ if @pinned_forum.save
+ redirect_to admins_topic_pinned_forums_path
+ flash[:success] = "新增精选文章成功"
+ else
+ redirect_to admins_topic_pinned_forums_path
+ flash[:danger] = "新增精选文章失败"
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ @pinned_forum.attributes = pinned_forum_params
+ if @pinned_forum.save
+ redirect_to admins_topic_pinned_forums_path
+ flash[:success] = "更新精选文章成功"
+ else
+ redirect_to admins_topic_pinned_forums_path
+ flash[:danger] = "更新精选文章失败"
+ end
+ end
+
+ def destroy
+ if @pinned_forum.destroy
+ redirect_to admins_topic_pinned_forums_path
+ flash[:success] = "删除精选文章成功"
+ else
+ redirect_to admins_topic_pinned_forums_path
+ flash[:danger] = "删除精选文章失败"
+ end
+ end
+
+ private
+ def find_pinned_forum
+ @pinned_forum = ::Topic::PinnedForum.find_by_id(params[:id])
+ end
+
+ def pinned_forum_params
+ params.require(:topic_pinned_forum).permit(:title, :uuid, :url, :order_index)
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/admins/users_controller.rb b/app/controllers/admins/users_controller.rb
index 98f0a6bfb..07ea8261e 100644
--- a/app/controllers/admins/users_controller.rb
+++ b/app/controllers/admins/users_controller.rb
@@ -1,4 +1,6 @@
class Admins::UsersController < Admins::BaseController
+ before_action :finder_user, except: [:index]
+
def index
params[:sort_by] = params[:sort_by].presence || 'created_on'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
@@ -8,12 +10,9 @@ class Admins::UsersController < Admins::BaseController
end
def edit
- @user = User.find(params[:id])
end
def update
- @user = User.find(params[:id])
-
Admins::UpdateUserService.call(@user, update_params)
flash[:success] = '保存成功'
redirect_to edit_admins_user_path(@user)
@@ -26,43 +25,47 @@ class Admins::UsersController < Admins::BaseController
end
def destroy
- User.find(params[:id]).destroy!
+ @user.destroy!
+ Gitea::User::DeleteService.call(@user.login)
render_delete_success
end
def lock
- User.find(params[:id]).lock!
+ @user.lock!
render_ok
end
def unlock
- User.find(params[:id]).activate!
+ @user.activate!
render_ok
end
def reward_grade
- user = User.find(params[:user_id])
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
def reset_login_times
- User.find(params[:id]).reset_login_times!
+ @user.reset_login_times!
render_ok
end
private
+ def finder_user
+ @user = User.find(params[:id])
+ end
+
def update_params
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
- password professional_certification authentication])
+ password professional_certification authentication login])
end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 816817411..70ccd69d0 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -70,49 +70,11 @@ class ApplicationController < ActionController::Base
(current_user.professional_certification && (ue.teacher? || ue.professional?))
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?
User.current.admin? || User.current.business?
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:绑定
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])$/
tip_exception(-2, "请输入正确的手机号或邮箱")
end
- # 考虑到安全参数问题,多一次查询,去掉Union
- user = User.where(phone: login).first || User.where(mail: login).first
- if type.to_i == 1 && !user.nil?
+
+ user_exist = Owner.exists?(phone: login) || Owner.exists?(mail: login)
+ if user_exist && type.to_i == 1
tip_exception(-2, "该手机号码或邮箱已被注册")
- elsif type.to_i == 2 && user.nil?
+ elsif type.to_i == 2 && !user_exist
tip_exception(-2, "该手机号码或邮箱未注册")
- elsif type.to_i == 3 && user.present?
+ elsif type.to_i == 3 && user_exist
tip_exception(-2, "该手机号码或邮箱已绑定")
end
- sucess_status
+ render_ok
end
# 发送及记录激活码
@@ -186,26 +148,6 @@ class ApplicationController < ActionController::Base
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)
normal_status(2, "参数") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
@@ -215,21 +157,6 @@ class ApplicationController < ActionController::Base
@page_size = params[:page_size] || 15
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
normal_status(403, "") unless User.current.admin?
end
@@ -681,7 +608,7 @@ class ApplicationController < ActionController::Base
def kaminari_paginate(relation)
limit = params[:limit] || params[:per_page]
- limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
+ limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
relation.page(page).per(limit)
@@ -689,7 +616,7 @@ class ApplicationController < ActionController::Base
def kaminari_array_paginate(relation)
limit = params[:limit] || params[:per_page]
- limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i
+ limit = (limit.to_i.zero? || limit.to_i > 20) ? 20 : limit.to_i
page = params[:page].to_i.zero? ? 1 : params[:page].to_i
Kaminari.paginate_array(relation).page(page).per(limit)
diff --git a/app/controllers/concerns/render_helper.rb b/app/controllers/concerns/render_helper.rb
index fad401539..81e85d1ce 100644
--- a/app/controllers/concerns/render_helper.rb
+++ b/app/controllers/concerns/render_helper.rb
@@ -3,8 +3,8 @@ module RenderHelper
render json: { status: 0, message: 'success' }.merge(data)
end
- def render_error(message = '')
- render json: { status: -1, message: message }
+ def render_error(status = -1, message = '')
+ render json: { status: status, message: message }
end
def render_not_acceptable(message = '请求已拒绝')
diff --git a/app/controllers/organizations/organizations_controller.rb b/app/controllers/organizations/organizations_controller.rb
index aedf285cd..b73d1efac 100644
--- a/app/controllers/organizations/organizations_controller.rb
+++ b/app/controllers/organizations/organizations_controller.rb
@@ -27,7 +27,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
def create
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!
@organization = Organizations::CreateService.call(current_user, organization_params)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb
new file mode 100644
index 000000000..207b45870
--- /dev/null
+++ b/app/controllers/topics_controller.rb
@@ -0,0 +1,9 @@
+class TopicsController < ApplicationController
+
+ def index
+ return render_not_found("请输入正确的数据类型") unless params[:topic_type].present?
+ scope = Topic.with_single_type(params[:topic_type])
+ @topics = kaminari_paginate(scope)
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/users/system_notification_histories_controller.rb b/app/controllers/users/system_notification_histories_controller.rb
new file mode 100644
index 000000000..70e91fbb9
--- /dev/null
+++ b/app/controllers/users/system_notification_histories_controller.rb
@@ -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
\ No newline at end of file
diff --git a/app/docs/slate/source/includes/_users.md b/app/docs/slate/source/includes/_users.md
index be2728d0b..218a1a4b7 100644
--- a/app/docs/slate/source/includes/_users.md
+++ b/app/docs/slate/source/includes/_users.md
@@ -199,6 +199,36 @@ await octokit.request('GET /api/users/:login/messages.json')
Success Data.
+## 用户阅读系统通知
+用户阅读系统通知
+
+> 示例:
+
+```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
diff --git a/app/forms/base_form.rb b/app/forms/base_form.rb
index 71eaee174..437217f00 100644
--- a/app/forms/base_form.rb
+++ b/app/forms/base_form.rb
@@ -23,7 +23,11 @@ class BaseForm
end
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
diff --git a/app/forms/register/base_form.rb b/app/forms/register/base_form.rb
new file mode 100644
index 000000000..df5abd871
--- /dev/null
+++ b/app/forms/register/base_form.rb
@@ -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
diff --git a/app/forms/register/check_columns_form.rb b/app/forms/register/check_columns_form.rb
new file mode 100644
index 000000000..20c5b1e89
--- /dev/null
+++ b/app/forms/register/check_columns_form.rb
@@ -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
diff --git a/app/forms/register/form.rb b/app/forms/register/form.rb
new file mode 100644
index 000000000..bad7a23e6
--- /dev/null
+++ b/app/forms/register/form.rb
@@ -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
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 01ffa41f1..f58436285 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -463,5 +463,11 @@ module ApplicationHelper
sidebar_item(url, "数据统计", icon: 'bar-chart', controller: 'root')
end
end
+
+ # 1 手机类型;0 邮箱类型
+ # 注意新版的login是自动名生成的
+ def phone_mail_type value
+ value =~ /^1\d{10}$/ ? 1 : 0
+ end
end
diff --git a/app/libs/custom_regexp.rb b/app/libs/custom_regexp.rb
index c7b5e7a1a..bbc061250 100644
--- a/app/libs/custom_regexp.rb
+++ b/app/libs/custom_regexp.rb
@@ -1,6 +1,7 @@
module CustomRegexp
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/
+ LOGIN = /^(?!_)(?!.*?_$)[a-zA-Z0-9_-]+$/ #只含有数字、字母、下划线不能以下划线开头和结尾
LASTNAME = /\A[a-zA-Z0-9\u4e00-\u9fa5]+\z/
NICKNAME = /\A[\u4e00-\u9fa5_a-zA-Z0-9]+\z/
PASSWORD = /\A[a-z_A-Z0-9\-\.!@#\$%\\\^&\*\)\(\+=\{\}\[\]\/",'_<>~\·`\?:;|]{8,16}\z/
diff --git a/app/libs/forum.rb b/app/libs/forum.rb
new file mode 100644
index 000000000..112ff2788
--- /dev/null
+++ b/app/libs/forum.rb
@@ -0,0 +1,20 @@
+module Forum
+ class << self
+ def forum_config
+ forum_config = {}
+
+ begin
+ config = Rails.application.config_for(:configuration).symbolize_keys!
+ forum_config = config[:forum].symbolize_keys!
+ raise 'forum config missing' if forum_config.blank?
+ rescue => ex
+ raise ex if Rails.env.production?
+
+ puts %Q{\033[33m [warning] forum config or configuration.yml missing,
+ please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m}
+ forum_config = {}
+ end
+ forum_config
+ end
+ end
+end
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 6e957b4df..acd34fbbd 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -1,17 +1,11 @@
class UserMailer < ApplicationMailer
# 注意:这个地方一定要和你的邮箱服务域名一致
- default from: 'educoder@trustie.org'
+ default from: 'notification@trustie.org'
# 用户注册验证码
def register_email(mail, code)
@code = code
- mail(to: mail, subject: '验证你的电子邮件')
+ mail(to: mail, subject: 'Gitink | 注册验证码')
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
diff --git a/app/models/reversed_keyword.rb b/app/models/reversed_keyword.rb
index cd8027fbd..10ad62fa0 100644
--- a/app/models/reversed_keyword.rb
+++ b/app/models/reversed_keyword.rb
@@ -18,6 +18,10 @@ class ReversedKeyword < ApplicationRecord
before_validation :set_identifier
+ def self.check_exists?(identifier)
+ self.is_reversed(identifier).exists?
+ end
+
private
def set_identifier
diff --git a/app/models/system_notification.rb b/app/models/system_notification.rb
index 6f901b3fd..d2b99ecf3 100644
--- a/app/models/system_notification.rb
+++ b/app/models/system_notification.rb
@@ -15,6 +15,13 @@ class SystemNotification < ApplicationRecord
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) }
+ def read_member?(user_id)
+ self.system_notification_histories.where(user_id: user_id).present? ? true : false
+ end
+
end
diff --git a/app/models/system_notification_history.rb b/app/models/system_notification_history.rb
new file mode 100644
index 000000000..b629babdf
--- /dev/null
+++ b/app/models/system_notification_history.rb
@@ -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
diff --git a/app/models/topic.rb b/app/models/topic.rb
new file mode 100644
index 000000000..13bf7b5bd
--- /dev/null
+++ b/app/models/topic.rb
@@ -0,0 +1,50 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+class Topic < ApplicationRecord
+
+ default_scope { order(order_index: :desc)}
+
+ scope :with_single_type, ->(type){where(type: trans_simpletype_to_classtype(type))}
+
+ def image
+ image_url('image')
+ end
+
+ def self.trans_simpletype_to_classtype(type)
+ case type
+ when 'activity_forum'
+ 'Topic::ActivityForum'
+ when 'banner'
+ 'Topic::Banner'
+ when 'card'
+ 'Topic::Card'
+ when 'cooperator'
+ 'Topic::Cooperator'
+ when 'excellent_project'
+ 'Topic::ExcellentProject'
+ when 'experience_forum'
+ 'Topic::ExperienceForum'
+ when 'pinned_forum'
+ 'Topic::PinnedForum'
+ end
+ end
+
+ private
+
+ def image_url(type)
+ return nil unless Util::FileManage.exists?(self, type)
+ Util::FileManage.source_disk_file_url(self, type)
+ end
+
+end
diff --git a/app/models/topic/activity_forum.rb b/app/models/topic/activity_forum.rb
new file mode 100644
index 000000000..8cf9adf83
--- /dev/null
+++ b/app/models/topic/activity_forum.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页平台动态
+class Topic::ActivityForum < Topic
+
+end
diff --git a/app/models/topic/banner.rb b/app/models/topic/banner.rb
new file mode 100644
index 000000000..e5b77bec0
--- /dev/null
+++ b/app/models/topic/banner.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页banner
+class Topic::Banner < Topic
+end
diff --git a/app/models/topic/card.rb b/app/models/topic/card.rb
new file mode 100644
index 000000000..6a54e17ea
--- /dev/null
+++ b/app/models/topic/card.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页卡片内容
+class Topic::Card < Topic
+end
diff --git a/app/models/topic/cooperator.rb b/app/models/topic/cooperator.rb
new file mode 100644
index 000000000..a023d3656
--- /dev/null
+++ b/app/models/topic/cooperator.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页合作伙伴
+class Topic::Cooperator < Topic
+end
diff --git a/app/models/topic/excellent_project.rb b/app/models/topic/excellent_project.rb
new file mode 100644
index 000000000..ac08863c7
--- /dev/null
+++ b/app/models/topic/excellent_project.rb
@@ -0,0 +1,17 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页优秀项目
+class Topic::ExcellentProject < Topic
+
+end
diff --git a/app/models/topic/experience_forum.rb b/app/models/topic/experience_forum.rb
new file mode 100644
index 000000000..855a56809
--- /dev/null
+++ b/app/models/topic/experience_forum.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页经验分享
+class Topic::ExperienceForum < Topic
+end
diff --git a/app/models/topic/pinned_forum.rb b/app/models/topic/pinned_forum.rb
new file mode 100644
index 000000000..c5a2c8572
--- /dev/null
+++ b/app/models/topic/pinned_forum.rb
@@ -0,0 +1,16 @@
+# == Schema Information
+#
+# Table name: topics
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# uuid :integer
+# image_url :string(255)
+# url :string(255)
+# order_index :integer
+#
+
+# 首页精选文章
+class Topic::PinnedForum < Topic
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 37f32c2f0..64cec9969 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -117,8 +117,6 @@ class User < Owner
enumerize :platform, in: [:forge, :educoder, :trustie, :military], default: :forge, scope: :shallow
belongs_to :laboratory, optional: true
- has_many :composes, dependent: :destroy
- has_many :compose_users, dependent: :destroy
has_one :user_extension, dependent: :destroy
has_many :open_users, dependent: :destroy
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_many :system_notification_histories
+ has_many :system_notifications, through: :system_notification_histories
+
# Groups and active users
scope :active, lambda { where(status: [STATUS_ACTIVE, STATUS_EDIT_INFO]) }
scope :like, lambda { |keywords|
@@ -440,6 +441,7 @@ class User < Owner
def activate!
update_attribute(:status, STATUS_ACTIVE)
+ prohibit_gitea_user_login!(false)
end
def register!
@@ -448,6 +450,12 @@ class User < Owner
def lock!
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
def need_edit_info!
diff --git a/app/queries/projects/list_query.rb b/app/queries/projects/list_query.rb
index 4f514b610..b06791bd3 100644
--- a/app/queries/projects/list_query.rb
+++ b/app/queries/projects/list_query.rb
@@ -11,20 +11,45 @@ class Projects::ListQuery < ApplicationQuery
end
def call
- q = params[:pinned].present? ? Project.pinned : Project
- q = q.visible.by_name_or_identifier(params[:search])
-
- scope = q
- .with_project_type(params[:project_type])
- .with_project_category(params[:category_id])
- .with_project_language(params[:language_id])
+ collection = Project.all
+ collection = filter_projects(collection)
sort = params[:sort_by] || "updated_on"
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
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
diff --git a/app/services/admins/update_user_service.rb b/app/services/admins/update_user_service.rb
index 6b1c0c857..34f704cbe 100644
--- a/app/services/admins/update_user_service.rb
+++ b/app/services/admins/update_user_service.rb
@@ -15,19 +15,13 @@ class Admins::UpdateUserService < ApplicationService
user.firstname = ''
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)
+ old_login = user.login
ActiveRecord::Base.transaction do
user.save!
user.user_extension.save!
- user.update!(is_shixun_marker: true) if user.is_certification_teacher
-
- update_gitlab_password if params[:password].present?
+ update_gitea_user(old_login)
end
user
@@ -36,7 +30,7 @@ class Admins::UpdateUserService < ApplicationService
private
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])
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])
end
- def update_gitlab_password
- return if user.gid.blank?
- # 同步修改gitlab密码
- Gitlab.client.edit_user(user.gid, password: params[:password])
+ def gitea_user_params
+ hash = {
+ password: params[:password].to_s.presence,
+ 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
Util.logger_error(ex)
raise Error, '保存失败'
diff --git a/app/services/forum/client_service.rb b/app/services/forum/client_service.rb
new file mode 100644
index 000000000..e3ff54691
--- /dev/null
+++ b/app/services/forum/client_service.rb
@@ -0,0 +1,94 @@
+class Forum::ClientService < ApplicationService
+ attr_reader :url, :params
+
+ PAGINATE_DEFAULT_PAGE = 1
+ PAGINATE_DEFAULT_LIMIT = 20
+
+ def initialize(options={})
+ @url = options[:url]
+ @params = options[:params]
+ end
+
+ def get(url, params={})
+ conn(params).get do |req|
+ req.url full_url(url, 'get')
+ params.except(:token).each_pair do |key, value|
+ req.params["#{key}"] = value
+ end
+ end
+
+ # response.headers.each do |k,v|
+ # puts "#{k}:#{v}"
+ # end #=> 响应头
+ end
+
+ private
+ def conn(auth={})
+ @client ||= begin
+ Faraday.new(url: domain) do |req|
+ req.request :url_encoded
+ req.headers['Content-Type'] = 'application/json'
+ req.response :logger # 显示日志
+ req.adapter Faraday.default_adapter
+ end
+ end
+ @client
+ end
+
+ def base_url
+ Forum.forum_config[:base_url]
+ end
+
+ def domain
+ Forum.forum_config[:domain]
+ end
+
+ def api_url
+ [domain, base_url].join('')
+ end
+
+ def full_url(api_rest, action='post')
+ url = [api_url, api_rest].join('').freeze
+ url = action === 'get' ? url : URI.escape(url)
+ url = URI.escape(url) unless url.ascii_only?
+ puts "[forum] request url: #{url}"
+ return url
+ end
+
+ def render_response(response)
+ status = response.status
+ body = response&.body
+
+ # log_error(status, body)
+
+ body, message = get_body_by_status(status, body)
+
+ [status, message, body]
+ end
+
+ def get_body_by_status(status, body)
+ body, message =
+ case status
+ when 401 then [nil, "401"]
+ when 404 then [nil, "404"]
+ when 403 then [nil, "403"]
+ when 500 then [nil, "500"]
+ else
+ if body.present?
+ body = JSON.parse(body)
+ fix_body(body)
+ else
+ nil
+ end
+ end
+
+ [body, message]
+ end
+
+ def fix_body(body)
+ return [body, nil] if body.is_a?(Array) || body.is_a?(Hash)
+
+ body['message'].blank? ? [body, nil] : [nil, body['message']]
+ end
+
+end
diff --git a/app/services/forum/memos/get_service.rb b/app/services/forum/memos/get_service.rb
new file mode 100644
index 000000000..c8ad56895
--- /dev/null
+++ b/app/services/forum/memos/get_service.rb
@@ -0,0 +1,21 @@
+class Forum::Memos::GetService < Forum::ClientService
+ attr_reader :memo_id
+
+ def initialize(memo_id)
+ @memo_id = memo_id
+ end
+
+ def call
+ response = get(url)
+ code, message, body = render_response(response)
+ if code == 200 && body["status"] == 0
+ return body
+ else
+ return nil
+ end
+ end
+
+ def url
+ "/memos/#{memo_id}.json".freeze
+ end
+end
\ No newline at end of file
diff --git a/app/services/gitea/client_service.rb b/app/services/gitea/client_service.rb
index 868a704c8..90843cc98 100644
--- a/app/services/gitea/client_service.rb
+++ b/app/services/gitea/client_service.rb
@@ -82,6 +82,8 @@ class Gitea::ClientService < ApplicationService
req.headers['Content-Type'] = 'application/json'
req.response :logger # 显示日志
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?
req.basic_auth(username, secret)
else
diff --git a/app/services/gitea/user/delete_service.rb b/app/services/gitea/user/delete_service.rb
new file mode 100644
index 000000000..5df3cb6b2
--- /dev/null
+++ b/app/services/gitea/user/delete_service.rb
@@ -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
diff --git a/app/services/users/register_service.rb b/app/services/users/register_service.rb
new file mode 100644
index 000000000..bb3b3ada1
--- /dev/null
+++ b/app/services/users/register_service.rb
@@ -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
diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb
index 06b12a6ed..2899d82a2 100644
--- a/app/views/admins/shared/_sidebar.html.erb
+++ b/app/views/admins/shared/_sidebar.html.erb
@@ -31,17 +31,30 @@
<%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %>
<%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %>
-
-
<%= sidebar_item(admins_faqs_path, 'FAQ', icon: 'question-circle', controller: 'admins-faqs') %>
<% end %>
- -->
+
<%= sidebar_item_group('#setting-system', '系统配置', icon: 'wrench') do %>
<%= sidebar_item(admins_sites_path, 'setting接口配置', icon: 'deaf', controller: 'admins-sites') %>
diff --git a/app/views/admins/topic/activity_forums/_form_modal.html.erb b/app/views/admins/topic/activity_forums/_form_modal.html.erb
new file mode 100644
index 000000000..3426337d2
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @activity_forum, url: {controller: "topic/activity_forums", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 帖子ID *
+
+ <%= p.text_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/_list.html.erb b/app/views/admins/topic/activity_forums/_list.html.erb
new file mode 100644
index 000000000..35068eddb
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 帖子ID
+ 排序等级
+ 操作
+
+
+
+ <% if activity_forums.present? %>
+ <% activity_forums.each_with_index do |activity_forum, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= activity_forum.title %>
+ <%= activity_forum.url %>
+ <%= activity_forum.uuid %>
+ <%= activity_forum.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_activity_forum_path(activity_forum), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_activity_forum_path(activity_forum), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: activity_forums } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/edit.js.erb b/app/views/admins/topic/activity_forums/edit.js.erb
new file mode 100644
index 000000000..b66ecd1c4
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/edit.js.erb
@@ -0,0 +1,2 @@
+$("#activity-forum-modals").html("<%= j render(partial: 'admins/topic/activity_forums/form_modal', locals: {type: 'update'}) %>")
+$(".activity-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/index.html.erb b/app/views/admins/topic/activity_forums/index.html.erb
new file mode 100644
index 000000000..a6d673d31
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('平台动态管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_activity_forums_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_activity_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/activity_forums/list', locals: { activity_forums: @activity_forums } %>
+
+
+
diff --git a/app/views/admins/topic/activity_forums/index.js.erb b/app/views/admins/topic/activity_forums/index.js.erb
new file mode 100644
index 000000000..3560c21f1
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/index.js.erb
@@ -0,0 +1 @@
+$('.activity-forum-list-container').html("<%= j( render partial: 'admins/topic/activity_forums/list', locals: { activity_forums: @activity_forums } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/activity_forums/new.js.erb b/app/views/admins/topic/activity_forums/new.js.erb
new file mode 100644
index 000000000..8e9a33097
--- /dev/null
+++ b/app/views/admins/topic/activity_forums/new.js.erb
@@ -0,0 +1,2 @@
+$("#activity-forum-modals").html("<%= j render(partial: 'admins/topic/activity_forums/form_modal', locals: {type: 'create'}) %>")
+$(".activity-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/_form_modal.html.erb b/app/views/admins/topic/banners/_form_modal.html.erb
new file mode 100644
index 000000000..20bca80c6
--- /dev/null
+++ b/app/views/admins/topic/banners/_form_modal.html.erb
@@ -0,0 +1,45 @@
+
+
+
+
+ <%= form_for @banner, url: {controller: "topic/banners", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+ <% logo_img = @banner.image %>
+
+
+ <%= file_field_tag(:image, accept: 'image/png,image/jpg,image/jpeg',style: "display: none", value: params[:image]) %>
+
+
+
+
logo
+
格式:PNG、JPG
+
尺寸:高度38px以内,宽等比例缩放
+
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/_list.html.erb b/app/views/admins/topic/banners/_list.html.erb
new file mode 100644
index 000000000..aa366ec21
--- /dev/null
+++ b/app/views/admins/topic/banners/_list.html.erb
@@ -0,0 +1,31 @@
+
+
+
+ 序号
+ 标题
+ 图片
+ 排序等级
+ 操作
+
+
+
+ <% if banners.present? %>
+ <% banners.each_with_index do |banner, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= banner.title %>
+
+ <%= banner.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_banner_path(banner), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_banner_path(banner), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: banners } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/edit.js.erb b/app/views/admins/topic/banners/edit.js.erb
new file mode 100644
index 000000000..524bb13a7
--- /dev/null
+++ b/app/views/admins/topic/banners/edit.js.erb
@@ -0,0 +1,18 @@
+$("#banner-modals").html("<%= j render(partial: 'admins/topic/banners/form_modal', locals: {type: 'update'}) %>")
+$(".banner-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/banners/index.html.erb b/app/views/admins/topic/banners/index.html.erb
new file mode 100644
index 000000000..e8ceefa2f
--- /dev/null
+++ b/app/views/admins/topic/banners/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('卡片管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_banners_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_banner_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/banners/list', locals: { banners: @banners } %>
+
+
+
diff --git a/app/views/admins/topic/banners/index.js.erb b/app/views/admins/topic/banners/index.js.erb
new file mode 100644
index 000000000..0095bd861
--- /dev/null
+++ b/app/views/admins/topic/banners/index.js.erb
@@ -0,0 +1 @@
+$('.banner-list-container').html("<%= j( render partial: 'admins/topic/banners/list', locals: { banners: @banners } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/banners/new.js.erb b/app/views/admins/topic/banners/new.js.erb
new file mode 100644
index 000000000..d1450eb7f
--- /dev/null
+++ b/app/views/admins/topic/banners/new.js.erb
@@ -0,0 +1,18 @@
+$("#banner-modals").html("<%= j render(partial: 'admins/topic/banners/form_modal', locals: {type: 'create'}) %>")
+$(".banner-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/cards/_form_modal.html.erb b/app/views/admins/topic/cards/_form_modal.html.erb
new file mode 100644
index 000000000..960b8b503
--- /dev/null
+++ b/app/views/admins/topic/cards/_form_modal.html.erb
@@ -0,0 +1,38 @@
+
+
+
+
+ <%= form_for @card, url: {controller: "topic/cards", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/_list.html.erb b/app/views/admins/topic/cards/_list.html.erb
new file mode 100644
index 000000000..71a460199
--- /dev/null
+++ b/app/views/admins/topic/cards/_list.html.erb
@@ -0,0 +1,31 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 排序等级
+ 操作
+
+
+
+ <% if cards.present? %>
+ <% cards.each_with_index do |card, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= card.title %>
+ <%= card.url %>
+ <%= card.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_card_path(card), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_card_path(card), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: cards } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/edit.js.erb b/app/views/admins/topic/cards/edit.js.erb
new file mode 100644
index 000000000..9d0ed0e74
--- /dev/null
+++ b/app/views/admins/topic/cards/edit.js.erb
@@ -0,0 +1,2 @@
+$("#card-modals").html("<%= j render(partial: 'admins/topic/cards/form_modal', locals: {type: 'update'}) %>")
+$(".card-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/index.html.erb b/app/views/admins/topic/cards/index.html.erb
new file mode 100644
index 000000000..6865fa107
--- /dev/null
+++ b/app/views/admins/topic/cards/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('卡片管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_cards_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_card_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/cards/list', locals: { cards: @cards } %>
+
+
+
diff --git a/app/views/admins/topic/cards/index.js.erb b/app/views/admins/topic/cards/index.js.erb
new file mode 100644
index 000000000..1bbcb5487
--- /dev/null
+++ b/app/views/admins/topic/cards/index.js.erb
@@ -0,0 +1 @@
+$('.card-list-container').html("<%= j( render partial: 'admins/topic/cards/list', locals: { cards: @cards } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/cards/new.js.erb b/app/views/admins/topic/cards/new.js.erb
new file mode 100644
index 000000000..94b8353b9
--- /dev/null
+++ b/app/views/admins/topic/cards/new.js.erb
@@ -0,0 +1,2 @@
+$("#card-modals").html("<%= j render(partial: 'admins/topic/cards/form_modal', locals: {type: 'create'}) %>")
+$(".card-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/_form_modal.html.erb b/app/views/admins/topic/cooperators/_form_modal.html.erb
new file mode 100644
index 000000000..8f9085292
--- /dev/null
+++ b/app/views/admins/topic/cooperators/_form_modal.html.erb
@@ -0,0 +1,51 @@
+
+
+
+
+ <%= form_for @cooperator, url: {controller: "topic/cooperators", action: "#{type}"}, html: { enctype: 'multipart/form-data' } do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+ <% logo_img = @cooperator.image %>
+
+
+ <%= file_field_tag(:image, accept: 'image/png,image/jpg,image/jpeg',style: "display: none", value: params[:image]) %>
+
+
+
+
logo
+
格式:PNG、JPG
+
尺寸:高度38px以内,宽等比例缩放
+
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/_list.html.erb b/app/views/admins/topic/cooperators/_list.html.erb
new file mode 100644
index 000000000..351b6b9de
--- /dev/null
+++ b/app/views/admins/topic/cooperators/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 图片
+ 排序等级
+ 操作
+
+
+
+ <% if cooperators.present? %>
+ <% cooperators.each_with_index do |cooperator, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= cooperator.title %>
+ <%= cooperator.url %>
+
+ <%= cooperator.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_cooperator_path(cooperator), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_cooperator_path(cooperator), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: cooperators } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/edit.js.erb b/app/views/admins/topic/cooperators/edit.js.erb
new file mode 100644
index 000000000..ec99bfcef
--- /dev/null
+++ b/app/views/admins/topic/cooperators/edit.js.erb
@@ -0,0 +1,18 @@
+$("#cooperator-modals").html("<%= j render(partial: 'admins/topic/cooperators/form_modal', locals: {type: 'update'}) %>")
+$(".cooperator-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/cooperators/index.html.erb b/app/views/admins/topic/cooperators/index.html.erb
new file mode 100644
index 000000000..e18bc397f
--- /dev/null
+++ b/app/views/admins/topic/cooperators/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('卡片管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_cooperators_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_cooperator_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/cooperators/list', locals: { cooperators: @cooperators } %>
+
+
+
diff --git a/app/views/admins/topic/cooperators/index.js.erb b/app/views/admins/topic/cooperators/index.js.erb
new file mode 100644
index 000000000..e3bbc044b
--- /dev/null
+++ b/app/views/admins/topic/cooperators/index.js.erb
@@ -0,0 +1 @@
+$('.cooperator-list-container').html("<%= j( render partial: 'admins/topic/cooperators/list', locals: { cooperators: @cooperators } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/cooperators/new.js.erb b/app/views/admins/topic/cooperators/new.js.erb
new file mode 100644
index 000000000..d986f4e7d
--- /dev/null
+++ b/app/views/admins/topic/cooperators/new.js.erb
@@ -0,0 +1,18 @@
+$("#cooperator-modals").html("<%= j render(partial: 'admins/topic/cooperators/form_modal', locals: {type: 'create'}) %>")
+$(".cooperator-change-modal").modal('show');
+
+$('.logo-item-left').on("change", 'input[type="file"]', function () {
+ var $fileInput = $(this);
+ var file = this.files[0];
+ var imageType = /image.*/;
+ if (file && file.type.match(imageType)) {
+ var reader = new FileReader();
+ reader.onload = function () {
+ var $box = $fileInput.parent();
+ $box.find('img').attr('src', reader.result).css('display', 'block');
+ $box.addClass('has-img');
+ };
+ reader.readAsDataURL(file);
+ } else {
+ }
+});
diff --git a/app/views/admins/topic/excellent_projects/_form_modal.html.erb b/app/views/admins/topic/excellent_projects/_form_modal.html.erb
new file mode 100644
index 000000000..4e48063b8
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @excellent_project, url: {controller: "topic/excellent_projects", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 项目ID *
+
+ <%= p.number_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/_list.html.erb b/app/views/admins/topic/excellent_projects/_list.html.erb
new file mode 100644
index 000000000..7642037db
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 项目ID
+ 排序等级
+ 操作
+
+
+
+ <% if excellent_projects.present? %>
+ <% excellent_projects.each_with_index do |excellent_project, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= excellent_project.title %>
+ <%= excellent_project.url %>
+ <%= excellent_project.uuid %>
+ <%= excellent_project.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_excellent_project_path(excellent_project), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_excellent_project_path(excellent_project), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: excellent_projects } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/edit.js.erb b/app/views/admins/topic/excellent_projects/edit.js.erb
new file mode 100644
index 000000000..d47b1a92a
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/edit.js.erb
@@ -0,0 +1,2 @@
+$("#excellent-project-modals").html("<%= j render(partial: 'admins/topic/excellent_projects/form_modal', locals: {type: 'update'}) %>")
+$(".excellent-project-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/index.html.erb b/app/views/admins/topic/excellent_projects/index.html.erb
new file mode 100644
index 000000000..1b529344b
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('优秀仓库管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_excellent_projects_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_excellent_project_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/excellent_projects/list', locals: { excellent_projects: @excellent_projects } %>
+
+
+
diff --git a/app/views/admins/topic/excellent_projects/index.js.erb b/app/views/admins/topic/excellent_projects/index.js.erb
new file mode 100644
index 000000000..969abd1e0
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/index.js.erb
@@ -0,0 +1 @@
+$('.excellent-project-list-container').html("<%= j( render partial: 'admins/topic/excellent_projects/list', locals: { excellent_projects: @excellent_projects } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/excellent_projects/new.js.erb b/app/views/admins/topic/excellent_projects/new.js.erb
new file mode 100644
index 000000000..1b7e13095
--- /dev/null
+++ b/app/views/admins/topic/excellent_projects/new.js.erb
@@ -0,0 +1,2 @@
+$("#excellent-project-modals").html("<%= j render(partial: 'admins/topic/excellent_projects/form_modal', locals: {type: 'create'}) %>")
+$(".excellent-project-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/_form_modal.html.erb b/app/views/admins/topic/experience_forums/_form_modal.html.erb
new file mode 100644
index 000000000..971b8ca51
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @experience_forum, url: {controller: "topic/experience_forums", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 帖子ID *
+
+ <%= p.number_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/_list.html.erb b/app/views/admins/topic/experience_forums/_list.html.erb
new file mode 100644
index 000000000..b6f5e91fc
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 帖子ID
+ 排序等级
+ 操作
+
+
+
+ <% if experience_forums.present? %>
+ <% experience_forums.each_with_index do |experience_forum, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= experience_forum.title %>
+ <%= experience_forum.url %>
+ <%= experience_forum.uuid %>
+ <%= experience_forum.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_experience_forum_path(experience_forum), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_experience_forum_path(experience_forum), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: experience_forums } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/edit.js.erb b/app/views/admins/topic/experience_forums/edit.js.erb
new file mode 100644
index 000000000..5684a1b1f
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/edit.js.erb
@@ -0,0 +1,2 @@
+$("#experience-forum-modals").html("<%= j render(partial: 'admins/topic/experience_forums/form_modal', locals: {type: 'update'}) %>")
+$(".experience-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/index.html.erb b/app/views/admins/topic/experience_forums/index.html.erb
new file mode 100644
index 000000000..e66738762
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('经验分享管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_experience_forums_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_experience_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/experience_forums/list', locals: { experience_forums: @experience_forums } %>
+
+
+
diff --git a/app/views/admins/topic/experience_forums/index.js.erb b/app/views/admins/topic/experience_forums/index.js.erb
new file mode 100644
index 000000000..9653cd9a8
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/index.js.erb
@@ -0,0 +1 @@
+$('.experience-forum-list-container').html("<%= j( render partial: 'admins/topic/experience_forums/list', locals: { experience_forums: @experience_forums } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/experience_forums/new.js.erb b/app/views/admins/topic/experience_forums/new.js.erb
new file mode 100644
index 000000000..5020e9ed1
--- /dev/null
+++ b/app/views/admins/topic/experience_forums/new.js.erb
@@ -0,0 +1,2 @@
+$("#experience-forum-modals").html("<%= j render(partial: 'admins/topic/experience_forums/form_modal', locals: {type: 'create'}) %>")
+$(".experience-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/_form_modal.html.erb b/app/views/admins/topic/pinned_forums/_form_modal.html.erb
new file mode 100644
index 000000000..45c6eb8ec
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/_form_modal.html.erb
@@ -0,0 +1,44 @@
+
+
+
+
+ <%= form_for @pinned_forum, url: {controller: "topic/pinned_forums", action: "#{type}"} do |p| %>
+
+
+
+ 标题 *
+
+ <%= p.text_field :title,class: "form-control input-lg",required: true%>
+
+
+
+ 跳转地址 *
+
+ <%= p.text_field :url,class: "form-control input-lg",required: true%>
+
+
+
+ 帖子ID *
+
+ <%= p.number_field :uuid,class: "form-control input-lg",required: true%>
+
+
+
+ 排序等级
+
+ <%= p.number_field :order_index, class: "form-control",placeholder: ""%>
+
+
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/_list.html.erb b/app/views/admins/topic/pinned_forums/_list.html.erb
new file mode 100644
index 000000000..9169b6a20
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/_list.html.erb
@@ -0,0 +1,33 @@
+
+
+
+ 序号
+ 标题
+ 跳转地址
+ 帖子ID
+ 排序等级
+ 操作
+
+
+
+ <% if pinned_forums.present? %>
+ <% pinned_forums.each_with_index do |pinned_forum, index| %>
+
+ <%= list_index_no((params[:page] || 1).to_i, index) %>
+ <%= pinned_forum.title %>
+ <%= pinned_forum.url %>
+ <%= pinned_forum.uuid %>
+ <%= pinned_forum.order_index %>
+
+ <%= link_to "编辑", edit_admins_topic_pinned_forum_path(pinned_forum), remote: true, class: "action" %>
+ <%= link_to "删除", admins_topic_pinned_forum_path(pinned_forum), method: :delete, data:{confirm: "确认删除的吗?"}, class: "action" %>
+
+
+ <% end %>
+ <% else %>
+ <%= render 'admins/shared/no_data_for_table' %>
+ <% end %>
+
+
+
+<%= render partial: 'admins/shared/paginate', locals: { objects: pinned_forums } %>
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/edit.js.erb b/app/views/admins/topic/pinned_forums/edit.js.erb
new file mode 100644
index 000000000..77875c679
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/edit.js.erb
@@ -0,0 +1,2 @@
+$("#pinned-forum-modals").html("<%= j render(partial: 'admins/topic/pinned_forums/form_modal', locals: {type: 'update'}) %>")
+$(".pinned-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/index.html.erb b/app/views/admins/topic/pinned_forums/index.html.erb
new file mode 100644
index 000000000..d6cf788b6
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/index.html.erb
@@ -0,0 +1,18 @@
+<% define_admin_breadcrumbs do %>
+ <% add_admin_breadcrumb('精选文章管理') %>
+<% end %>
+
+
+ <%= form_tag(admins_topic_pinned_forums_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
+ <%= text_field_tag(:search, params[:search], class: 'form-control col-12 col-md-2 mr-3', placeholder: '标题检索') %>
+ <%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
+
+ <% end %>
+ <%= link_to "新增", new_admins_topic_pinned_forum_path, remote: true, class: "btn btn-primary pull-right", "data-disabled-with":"...新增" %>
+
+
+
+ <%= render partial: 'admins/topic/pinned_forums/list', locals: { pinned_forums: @pinned_forums } %>
+
+
+
diff --git a/app/views/admins/topic/pinned_forums/index.js.erb b/app/views/admins/topic/pinned_forums/index.js.erb
new file mode 100644
index 000000000..78d1a240a
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/index.js.erb
@@ -0,0 +1 @@
+$('.pinned-forum-list-container').html("<%= j( render partial: 'admins/topic/pinned_forums/list', locals: { pinned_forums: @pinned_forums } ) %>");
\ No newline at end of file
diff --git a/app/views/admins/topic/pinned_forums/new.js.erb b/app/views/admins/topic/pinned_forums/new.js.erb
new file mode 100644
index 000000000..1069707c0
--- /dev/null
+++ b/app/views/admins/topic/pinned_forums/new.js.erb
@@ -0,0 +1,2 @@
+$("#pinned-forum-modals").html("<%= j render(partial: 'admins/topic/pinned_forums/form_modal', locals: {type: 'create'}) %>")
+$(".pinned-forum-change-modal").modal('show');
\ No newline at end of file
diff --git a/app/views/admins/users/edit.html.erb b/app/views/admins/users/edit.html.erb
index 5abc82711..44d524997 100644
--- a/app/views/admins/users/edit.html.erb
+++ b/app/views/admins/users/edit.html.erb
@@ -7,8 +7,8 @@
- <%= 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 %>
+
<% end %>
<%= @user.real_name %> | <%= @user.id %> | <%= @user.login %>
@@ -50,6 +50,10 @@
基本信息
diff --git a/app/views/admins/users/shared/_user_list.html.erb b/app/views/admins/users/shared/_user_list.html.erb
index 5c033d282..ae4657b5e 100644
--- a/app/views/admins/users/shared/_user_list.html.erb
+++ b/app/views/admins/users/shared/_user_list.html.erb
@@ -18,7 +18,7 @@
<%= list_index_no((params[:page] || 1).to_i, index) %>
- <%= link_to "/users/#{user.login}", target: '_blank' do %>
+ <%= link_to "/#{user.login}", target: '_blank' do %>
<%= overflow_hidden_span user.real_name, width: 100 %>
<% end %>
@@ -44,7 +44,6 @@
<%= javascript_void_link('更多', class: 'action dropdown-toggle', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false) %>