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 @@ + \ 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 @@ + + + + + + + + + + + + + <% if activity_forums.present? %> + <% activity_forums.each_with_index do |activity_forum, index| %> + + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题跳转地址帖子ID排序等级操作
    <%= 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" %> +
    + +<%= 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 @@ + \ 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| %> + + + + + + + + <% 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":"...新增" %> +
    + + + 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 @@ + \ 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| %> + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题跳转地址排序等级操作
    <%= 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" %> +
    + +<%= 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 @@ + \ 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| %> + + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题跳转地址图片排序等级操作
    <%= 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" %> +
    + +<%= 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 @@ + \ 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 @@ + + + + + + + + + + + + + <% if excellent_projects.present? %> + <% excellent_projects.each_with_index do |excellent_project, index| %> + + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题跳转地址项目ID排序等级操作
    <%= 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" %> +
    + +<%= 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 @@ + \ 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 @@ + + + + + + + + + + + + + <% if experience_forums.present? %> + <% experience_forums.each_with_index do |experience_forum, index| %> + + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题跳转地址帖子ID排序等级操作
    <%= 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" %> +
    + +<%= 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 @@ + \ 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 @@ + + + + + + + + + + + + + <% if pinned_forums.present? %> + <% pinned_forums.each_with_index do |pinned_forum, index| %> + + + + + + + + + <% end %> + <% else %> + <%= render 'admins/shared/no_data_for_table' %> + <% end %> + +
    序号标题跳转地址帖子ID排序等级操作
    <%= 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" %> +
    + +<%= 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 %>