| @@ -0,0 +1,44 @@ | |||
| class Admins::MessageTemplatesController < Admins::BaseController | |||
| before_action :get_template, only: [:edit, :update, :destroy] | |||
| def index | |||
| message_templates = MessageTemplate.group(:type).count.keys | |||
| @message_templates = kaminari_array_paginate(message_templates) | |||
| end | |||
| def edit | |||
| end | |||
| def update | |||
| if @message_template.update_attributes(message_template_params) | |||
| redirect_to admins_message_templates_path | |||
| flash[:success] = '消息模版更新成功' | |||
| else | |||
| redirect_to admins_message_templates_path | |||
| flash[:danger] = @message_template.errors.full_messages.join(",") | |||
| end | |||
| end | |||
| def init_data | |||
| if MessageTemplate.build_init_data | |||
| redirect_to admins_message_templates_path | |||
| flash[:success] = '消息模版初始化成功' | |||
| else | |||
| redirect_to admins_message_templates_path | |||
| flash[:danger] = '消息模版初始化失败' | |||
| end | |||
| end | |||
| private | |||
| def message_template_params | |||
| params.require(@message_template.type.split("::").join("_").underscore.to_sym).permit! | |||
| end | |||
| def get_template | |||
| @message_template = MessageTemplate.find_by(id: params[:id]) | |||
| unless @message_template.present? | |||
| redirect_to admins_message_templates_path | |||
| flash[:danger] = "消息模版不存在" | |||
| end | |||
| end | |||
| end | |||
| @@ -111,6 +111,8 @@ class IssuesController < ApplicationController | |||
| Issues::CreateForm.new({subject:issue_params[:subject]}).validate! | |||
| @issue = Issue.new(issue_params) | |||
| if @issue.save! | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) | |||
| SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @issue&.id) | |||
| if params[:attachment_ids].present? | |||
| params[:attachment_ids].each do |id| | |||
| attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id) | |||
| @@ -158,6 +160,7 @@ class IssuesController < ApplicationController | |||
| def update | |||
| last_token = @issue.token | |||
| last_status_id = @issue.status_id | |||
| @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank? | |||
| if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | |||
| @issue&.issue_tags_relates&.destroy_all | |||
| params[:issue_tag_ids].each do |tag| | |||
| @@ -202,6 +205,20 @@ class IssuesController < ApplicationController | |||
| issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id) | |||
| Issues::UpdateForm.new({subject:issue_params[:subject]}).validate! | |||
| if @issue.update_attributes(issue_params) | |||
| if @issue&.pull_request.present? | |||
| SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) | |||
| SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @issue&.pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? | |||
| else | |||
| previous_changes = @issue.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name) | |||
| if @issue.previous_changes[:start_date].present? | |||
| previous_changes.merge!(start_date: [@issue.previous_changes[:start_date][0].to_s, @issue.previous_changes[:start_date][1].to_s]) | |||
| end | |||
| if @issue.previous_changes[:due_date].present? | |||
| previous_changes.merge!(due_date: [@issue.previous_changes[:due_date][0].to_s, @issue.previous_changes[:due_date][1].to_s]) | |||
| end | |||
| SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, @issue&.id, previous_changes) | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if @issue.previous_changes[:assigned_to_id].present? | |||
| end | |||
| if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时 | |||
| @issue.issue_times.update_all(end_time: Time.now) | |||
| @issue.update_closed_issues_count_in_project! | |||
| @@ -253,6 +270,7 @@ class IssuesController < ApplicationController | |||
| status_id = @issue.status_id | |||
| token = @issue.token | |||
| login = @issue.user.try(:login) | |||
| SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, @issue&.subject, @issue.assigned_to_id, @issue.author_id) | |||
| if @issue.destroy | |||
| if issue_type == "2" && status_id != 5 | |||
| post_to_chain("add", token, login) | |||
| @@ -272,8 +290,12 @@ class IssuesController < ApplicationController | |||
| def clean | |||
| #批量删除,暂时只能删除未悬赏的 | |||
| issue_ids = params[:ids] | |||
| if issue_ids.present? | |||
| if Issue.where(id: issue_ids, issue_type: "1").destroy_all | |||
| issues = Issue.where(id: issue_ids, issue_type: "1") | |||
| if issues.present? | |||
| issues.find_each do |i| | |||
| SendTemplateMessageJob.perform_later('IssueDeleted', current_user.id, i&.subject, i.assigned_to_id, i.author_id) | |||
| end | |||
| if issues.destroy_all | |||
| normal_status(0, "删除成功") | |||
| else | |||
| normal_status(-1, "删除失败") | |||
| @@ -307,7 +329,18 @@ class IssuesController < ApplicationController | |||
| if update_hash.blank? | |||
| normal_status(-1, "请选择批量更新内容") | |||
| elsif issues&.update(update_hash) | |||
| issues.map{|i| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present?} | |||
| issues.each do |i| | |||
| i.create_journal_detail(false, [], [], current_user&.id) if i.previous_changes.present? | |||
| previous_changes = i.previous_changes.slice(:status_id, :assigned_to_id, :tracker_id, :priority_id, :fixed_version_id, :done_ratio, :issue_tags_value, :branch_name) | |||
| if i.previous_changes[:start_date].present? | |||
| previous_changes.merge!(start_date: [i.previous_changes[:start_date][0].to_s, i.previous_changes[:start_date][1].to_s]) | |||
| end | |||
| if i.previous_changes[:due_date].present? | |||
| previous_changes.merge!(due_date: [i.previous_changes[:due_date][0].to_s, i.previous_changes[:due_date][1].to_s]) | |||
| end | |||
| SendTemplateMessageJob.perform_later('IssueChanged', current_user.id, i&.id, previous_changes) | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, i&.id) if i.previous_changes[:assigned_to_id].present? | |||
| end | |||
| normal_status(0, "批量更新成功") | |||
| else | |||
| normal_status(-1, "批量更新失败") | |||
| @@ -321,6 +354,8 @@ class IssuesController < ApplicationController | |||
| @new_issue = @issue.dup | |||
| @new_issue.author_id = current_user.id | |||
| if @new_issue.save | |||
| SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @new_issue&.id) | |||
| SendTemplateMessageJob.perform_later('ProjectIssue', current_user.id, @new_issue&.id) | |||
| issue_tags = @issue.issue_tags.pluck(:id) | |||
| if issue_tags.present? | |||
| issue_tags.each do |tag| | |||
| @@ -398,22 +433,22 @@ class IssuesController < ApplicationController | |||
| def check_project_public | |||
| unless @project.is_public || @project.member?(current_user) || current_user.admin? || (@project.user_id == current_user.id) | |||
| normal_status(-1, "您没有权限") | |||
| return render_forbidden | |||
| end | |||
| end | |||
| def set_issue | |||
| @issue = Issue.find_by_id(params[:id]) | |||
| if @issue.blank? | |||
| normal_status(-1, "标签不存在") | |||
| elsif @issue.is_lock &&!(@project.member?(current_user) || current_user.admin?) | |||
| normal_status(-1, "您没有权限") | |||
| return render_not_found | |||
| elsif !(@project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id)))) | |||
| return render_forbidden | |||
| end | |||
| end | |||
| def check_issue_permission | |||
| unless @project.is_public || (current_user.present? && (@project.member?(current_user) || current_user&.admin? || (@project.user_id == current_user&.id))) | |||
| normal_status(-1, "您没有权限") | |||
| return render_forbidden | |||
| end | |||
| end | |||
| @@ -9,6 +9,8 @@ class MembersController < ApplicationController | |||
| def create | |||
| interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user) | |||
| SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) | |||
| SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) | |||
| render_response(interactor) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -28,6 +30,8 @@ class MembersController < ApplicationController | |||
| def remove | |||
| interactor = Projects::DeleteMemberInteractor.call(@project.owner, @project, @user) | |||
| SendTemplateMessageJob.perform_later('ProjectLeft', current_user.id, @user.id, @project.id) | |||
| SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, @user.id, @project.id) | |||
| render_response(interactor) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -36,6 +40,7 @@ class MembersController < ApplicationController | |||
| def change_role | |||
| interactor = Projects::ChangeMemberRoleInteractor.call(@project.owner, @project, @user, params[:role]) | |||
| SendTemplateMessageJob.perform_later('ProjectRole', current_user.id, @user.id, @project.id, message_role_name) | |||
| render_response(interactor) | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -66,4 +71,14 @@ class MembersController < ApplicationController | |||
| def check_user_profile_completed | |||
| require_user_profile_completed(@user) | |||
| end | |||
| def message_role_name | |||
| case params[:role] | |||
| when 'Manager' then '管理员' | |||
| when 'Developer' then '开发者' | |||
| when 'Reporter' then '报告者' | |||
| else | |||
| '' | |||
| end | |||
| end | |||
| end | |||
| @@ -18,6 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController | |||
| ActiveRecord::Base.transaction do | |||
| @team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id) | |||
| @organization_user = OrganizationUser.build(@organization.id, @operate_user.id) | |||
| SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) | |||
| Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login) | |||
| end | |||
| rescue Exception => e | |||
| @@ -6,7 +6,8 @@ class Projects::ProjectUnitsController < Projects::BaseController | |||
| def create | |||
| if current_user.admin? || @project.manager?(current_user) | |||
| ActiveRecord::Base.transaction do | |||
| ProjectUnit.update_by_unit_types!(@project, unit_types) | |||
| before_units, after_units = ProjectUnit.update_by_unit_types!(@project, unit_types) | |||
| SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, {navbar: true}) unless before_units.eql?(after_units) | |||
| render_ok | |||
| end | |||
| else | |||
| @@ -139,6 +139,7 @@ class ProjectsController < ApplicationController | |||
| @project.repository.update_column(:hidden, private) | |||
| end | |||
| end | |||
| SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public)) | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| @@ -59,6 +59,8 @@ class PullRequestsController < ApplicationController | |||
| @pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params) | |||
| if @gitea_pull_request[:status] == :success | |||
| @pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"]) | |||
| SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) | |||
| SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) | |||
| render_ok | |||
| else | |||
| render_error("create pull request error: #{@gitea_pull_request[:status]}") | |||
| @@ -77,12 +79,13 @@ class PullRequestsController < ApplicationController | |||
| if params[:title].nil? | |||
| normal_status(-1, "名称不能为空") | |||
| elsif params[:issue_tag_ids].nil? | |||
| normal_status(-1, "标签不能为空") | |||
| normal_status(-1, "标记不能为空") | |||
| else | |||
| ActiveRecord::Base.transaction do | |||
| begin | |||
| merge_params | |||
| @issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank? | |||
| if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists? | |||
| @issue&.issue_tags_relates&.destroy_all | |||
| params[:issue_tag_ids].each do |tag| | |||
| @@ -116,6 +119,8 @@ class PullRequestsController < ApplicationController | |||
| normal_status(-1, e.message) | |||
| raise ActiveRecord::Rollback | |||
| end | |||
| SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) | |||
| SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id ) if @issue.previous_changes[:assigned_to_id].present? | |||
| end | |||
| end | |||
| @@ -125,7 +130,12 @@ class PullRequestsController < ApplicationController | |||
| ActiveRecord::Base.transaction do | |||
| begin | |||
| colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user) | |||
| colsed === true ? normal_status(1, "已拒绝") : normal_status(-1, '合并失败') | |||
| if colsed === true | |||
| SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) | |||
| normal_status(1, "已拒绝") | |||
| else | |||
| normal_status(-1, '合并失败') | |||
| end | |||
| rescue => e | |||
| normal_status(-1, e.message) | |||
| raise ActiveRecord::Rollback | |||
| @@ -164,6 +174,7 @@ class PullRequestsController < ApplicationController | |||
| if success_condition && @pull_request.merge! | |||
| @pull_request.project_trend_status! | |||
| @issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id) | |||
| SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) | |||
| normal_status(1, "合并成功") | |||
| else | |||
| normal_status(-1, result.message) | |||
| @@ -0,0 +1,96 @@ | |||
| class Users::MessagesController < Users::BaseController | |||
| before_action :private_user_resources! | |||
| before_action :find_receivers, only: [:create] | |||
| def index | |||
| limit = params[:limit] || params[:per_page] | |||
| limit = (limit.to_i.zero? || limit.to_i > 15) ? 15 : limit.to_i | |||
| page = params[:page].to_i.zero? ? 1 : params[:page].to_i | |||
| result = Notice::Read::ListService.call(observed_user.id, message_type, message_status, page, limit) | |||
| return render_error if result.nil? | |||
| @data = result[2] | |||
| end | |||
| def create | |||
| return render_forbidden unless %w(atme).include?(params[:type]) | |||
| case params[:type] | |||
| when 'atme' | |||
| Notice::Write::CreateAtmeForm.new(atme_params).validate! | |||
| case atme_params[:atmeable_type] | |||
| when 'Issue' | |||
| SendTemplateMessageJob.perform_now('IssueAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| when 'PullRequest' | |||
| SendTemplateMessageJob.perform_now('PullRequestAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| when 'Journal' | |||
| journal = Journal.find_by_id(atme_params[:atmeable_id]) | |||
| if journal.present? | |||
| if journal&.issue&.pull_request.present? | |||
| SendTemplateMessageJob.perform_now('PullRequestAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| else | |||
| SendTemplateMessageJob.perform_now('IssueAtme', @receivers, current_user.id, atme_params[:atmeable_id]) | |||
| end | |||
| end | |||
| end | |||
| end | |||
| render_ok | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def delete | |||
| return render_forbidden unless %w(atme).include?(params[:type]) | |||
| result = Notice::Write::DeleteService.call(params[:ids], observed_user.id, message_type) | |||
| return render_error if result.nil? | |||
| render_ok | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| def read | |||
| return render_forbidden unless %w(notification atme).include?(params[:type]) | |||
| result = Notice::Write::ChangeStatusService.call(params[:ids], observed_user.id, message_type) | |||
| if result.nil? | |||
| render_error | |||
| else | |||
| render_ok | |||
| end | |||
| rescue Exception => e | |||
| uid_logger_error(e.message) | |||
| tip_exception(e.message) | |||
| end | |||
| private | |||
| def message_type | |||
| @message_type = begin | |||
| case params[:type] | |||
| when "notification" then 1 | |||
| when "atme" then 2 | |||
| else | |||
| -1 | |||
| end | |||
| end | |||
| end | |||
| def message_status | |||
| @message_status = begin | |||
| case params[:status] | |||
| when "1" then 1 | |||
| when "2" then 2 | |||
| else | |||
| -1 | |||
| end | |||
| end | |||
| end | |||
| def atme_params | |||
| params.permit(:atmeable_type, :atmeable_id, receivers_login: []) | |||
| end | |||
| def find_receivers | |||
| @receivers = User.where(login: params[:receivers_login]) | |||
| return render_not_found if @receivers.size == 0 | |||
| end | |||
| end | |||
| @@ -91,6 +91,12 @@ class UsersController < ApplicationController | |||
| def get_user_info | |||
| begin | |||
| @user = current_user | |||
| begin | |||
| result = Notice::Read::CountService.call(current_user.id) | |||
| @message_unread_total = result.nil? ? 0 : result[2]["unread_notification"] | |||
| rescue | |||
| @message_unread_total = 0 | |||
| end | |||
| # TODO 等消息上线再打开注释 | |||
| #@tidding_count = unviewed_tiddings(current_user) if current_user.present? | |||
| rescue Exception => e | |||
| @@ -1,7 +1,7 @@ | |||
| <!-- | |||
| * @Date: 2021-03-01 10:35:21 | |||
| * @LastEditors: viletyy | |||
| * @LastEditTime: 2021-06-11 16:28:51 | |||
| * @LastEditTime: 2021-09-15 18:00:10 | |||
| * @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md | |||
| --> | |||
| # Users | |||
| @@ -47,6 +47,275 @@ await octokit.request('GET /api/users/me.json') | |||
| Success Data. | |||
| </aside> | |||
| ## 用户消息列表 | |||
| 获取用户消息列表 | |||
| > 示例: | |||
| ```shell | |||
| curl -X GET http://localhost:3000/api/users/:login/messages.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('GET /api/users/:login/messages.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `GET api/users/yystopf/messages.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型,不传为所有消息,notification为系统消息,atme为@我消息| | |||
| |status | integer | 是否已读,不传为所有消息,1为未读,2为已读 | | |||
| |limit | integer | 每页个数 | | |||
| |page | integer | 页码 | | |||
| ### 返回字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |total_count | integer | 消息总数 | | |||
| |type | string | 消息类型 | | |||
| |unread_notification | integer | 未读系统通知数量 | | |||
| |unread_atme | integer | 未读@我数量 | | |||
| |messages.id | integer | 消息id | | |||
| |messages.status | integer | 消息是否已读,1为未读,2为已读 | | |||
| |messages.content | string | 消息内容 | | |||
| |messages.notification_url | string | 消息跳转地址 | | |||
| |messages.source | string | 消息来源 | | |||
| |messages.timeago | string | 消息时间 | | |||
| |messages.type | string | 消息类型,notification为系统消息,atme为@我消息| | |||
| |sender | object | 消息发送者 | | |||
| #### 消息来源source字段说明 | |||
| 类型|说明 | |||
| --------- | ----------- | |||
| |IssueAssigned | 有新指派给我的易修 | | |||
| |IssueAssignerExpire | 我负责的易修截止日期到达最后一天 | | |||
| |IssueAtme | 在易修中@我 | | |||
| |IssueChanged | 我创建或负责的易修状态变更 | | |||
| |IssueCreatorExpire | 我创建的易修截止日期到达最后一天 | | |||
| |IssueDeleted | 我创建或负责的易修删除 | | |||
| |IssueJournal | 我创建或负责的易修有新的评论 | | |||
| |LoginIpTip | 登录异常提示 | | |||
| |OrganizationJoined | 账号被拉入组织 | | |||
| |OrganizationLeft | 账号被移出组织 | | |||
| |OrganizationRole | 账号组织权限变更 | | |||
| |ProjectDeleted | 我关注的仓库被删除 | | |||
| |ProjectFollowed | 我管理的仓库被关注 | | |||
| |ProjectForked | 我管理的仓库被复刻 | | |||
| |ProjectIssue | 我管理/关注的仓库有新的易修 | | |||
| |ProjectJoined | 账号被拉入项目 | | |||
| |ProjectLeft | 账号被移出项目 | | |||
| |ProjectMemberJoined | 我管理的仓库有成员加入 | | |||
| |ProjectMemberLeft | 我管理的仓库有成员移出 | | |||
| |ProjectMilestone | 我管理的仓库有新的里程碑 | | |||
| |ProjectPraised | 我管理的仓库被点赞 | | |||
| |ProjectPullRequest | 我管理/关注的仓库有新的合并请求 | | |||
| |ProjectRole | 账号仓库权限变更 | | |||
| |ProjectSettingChanged | 我管理的仓库项目设置被更改 | | |||
| |ProjectTransfer | 我关注的仓库被转移 | | |||
| |ProjectVersion | 我关注的仓库有新的发行版 | | |||
| |PullRequestAssigned | 有新指派给我的合并请求 | | |||
| |PullReuqestAtme | 在合并请求中@我 | | |||
| |PullRequestChanged | 我创建或负责的合并请求状态变更 | | |||
| |PullRequestClosed | 我创建或负责的合并请求被关闭 | | |||
| |PullRequestJournal | 我创建或负责的合并请求有新的评论 | | |||
| |PullRequestMerged | 我创建或负责的合并请求被合并 | | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "total_count": 5, | |||
| "type": "", | |||
| "unread_notification": 3, | |||
| "unread_atme": 2, | |||
| "messages": [ | |||
| { | |||
| "id": 1, | |||
| "status": 1, | |||
| "content": "Atme Message Content 1", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "PullRequestAtme", | |||
| "time_ago": "1天前", | |||
| "type": "atme", | |||
| "sender": { | |||
| "id": 5, | |||
| "type": "User", | |||
| "name": "testforge2", | |||
| "login": "testforge2", | |||
| "image_url": "system/lets/letter_avatars/2/T/236_177_85/120.png" | |||
| } | |||
| }, | |||
| { | |||
| "id": 2, | |||
| "status": 0, | |||
| "content": "Atme Message Content 2", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "IssueAtme", | |||
| "time_ago": "1天前", | |||
| "type": "atme", | |||
| "sender": { | |||
| "id": 4, | |||
| "type": "User", | |||
| "name": "testforge1", | |||
| "login": "testforge1", | |||
| "image_url": "system/lets/letter_avatars/2/T/19_237_174/120.png" | |||
| } | |||
| }, | |||
| { | |||
| "id": 3, | |||
| "status": 1, | |||
| "content": "Notification Message Content 1", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "IssueDelete", | |||
| "time_ago": "1天前", | |||
| "type": "notification" | |||
| }, | |||
| { | |||
| "id": 4, | |||
| "status": 0, | |||
| "content": "Notification Message Content 2", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "IssueChanged", | |||
| "time_ago": "1天前", | |||
| "type": "notification" | |||
| }, | |||
| { | |||
| "id": 5, | |||
| "status": 0, | |||
| "content": "Notification Message Content 3", | |||
| "notification_url": "http://www.baidu.com", | |||
| "source": "ProjectJoined", | |||
| "time_ago": "1天前", | |||
| "type": "notification" | |||
| } | |||
| ] | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 发送消息 | |||
| 发送消息, 目前只支持atme | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/users/:login/messages.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/users/:login/messages.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST api/users/yystopf/messages.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型 | | |||
| |receivers_login | array | 需要发送消息的用户名数组| | |||
| |atmeable_type | string | atme消息对象,是从哪里@我的,比如评论:Journal、易修:Issue、合并请求:PullRequest | | |||
| |atmeable_id | integer | atme消息对象id | | |||
| > 请求的JSON示例: | |||
| ```json | |||
| { | |||
| "type": "atme", | |||
| "receivers_login": ["yystopf", "testforge1"], | |||
| "atmeable_type": "Journal", | |||
| "atmeable_id": 67 | |||
| } | |||
| ``` | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 阅读消息 | |||
| 阅读消息 | |||
| > 示例: | |||
| ```shell | |||
| curl -X POST http://localhost:3000/api/users/:login/messages/read.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('POST /api/users/:login/messages/read.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `POST api/users/yystopf/messages/read.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型,不传为所有消息,notification为系统消息,atme为@我消息| | |||
| |ids | array | 消息id数组,包含-1则把所有未读消息标记为已读| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 删除消息 | |||
| 删除消息 | |||
| > 示例: | |||
| ```shell | |||
| curl -X DELETE http://localhost:3000/api/users/:login/messages.json | |||
| ``` | |||
| ```javascript | |||
| await octokit.request('DELETE /api/users/:login/messages.json') | |||
| ``` | |||
| ### HTTP 请求 | |||
| `DELETE api/users/yystopf/messages.json` | |||
| ### 请求字段说明: | |||
| 参数 | 类型 | 字段说明 | |||
| --------- | ----------- | ----------- | |||
| |type | string | 消息类型,atme为@我消息| | |||
| |ids | array | 消息id数组,包含-1则把所有消息删除| | |||
| > 返回的JSON示例: | |||
| ```json | |||
| { | |||
| "status": 0, | |||
| "message": "success" | |||
| } | |||
| ``` | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| ## 更改用户信息 | |||
| 更改用户信息 | |||
| @@ -2,11 +2,15 @@ class BaseForm | |||
| include ActiveModel::Model | |||
| def check_project_category(project_category_id) | |||
| raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id) | |||
| unless project_category_id == '' | |||
| raise "project_category_id参数值无效." if project_category_id && !ProjectCategory.exists?(project_category_id) | |||
| end | |||
| end | |||
| def check_project_language(project_language_id) | |||
| raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id) | |||
| unless project_language_id == '' | |||
| raise "project_language_id参数值无效." if project_language_id && !ProjectLanguage.exists?(project_language_id) | |||
| end | |||
| end | |||
| def check_repository_name(user_id, repository_name) | |||
| @@ -0,0 +1,23 @@ | |||
| class Notice::Write::CreateAtmeForm | |||
| include ActiveModel::Model | |||
| attr_accessor :receivers_login, :atmeable_type, :atmeable_id | |||
| validate :check_receivers | |||
| def check_receivers | |||
| receivers_login.each do |login| | |||
| receiver = User.find_by(login: login) || User.find_by_id(login) | |||
| raise 'receivers_login值无效.' unless receiver.present? | |||
| end | |||
| end | |||
| def check_atmeable | |||
| begin | |||
| raise 'atmeable对象无效.' unless atmeable_type.constantize.find_by_id(atmeable_id).present? | |||
| rescue => exception | |||
| raise 'atmeable对象无效.' | |||
| end | |||
| end | |||
| end | |||
| @@ -1,6 +1,6 @@ | |||
| class Projects::UpdateForm < BaseForm | |||
| attr_accessor :name, :description, :project_category_id, :project_language_id, :private | |||
| validates :name, :description, :project_category_id, :project_language_id, presence: true | |||
| validates :name, presence: true | |||
| validates :name, length: { maximum: 50 } | |||
| validates :description, length: { maximum: 200 } | |||
| validate do | |||
| @@ -18,12 +18,30 @@ class BroadcastMirrorRepoMsgJob < ApplicationJob | |||
| id: project.id, | |||
| type: project.numerical_for_project_type | |||
| } | |||
| # 新增失败重试机制, 重试三次 | |||
| result = broadcast(project, json_data) | |||
| if result == 0 | |||
| count = 3 | |||
| while count > 0 | |||
| sleep 3.seconds | |||
| result = broadcast(project, json_data) | |||
| if result > 0 | |||
| break | |||
| end | |||
| count -= 1 | |||
| end | |||
| end | |||
| end | |||
| def broadcast(project, json_data) | |||
| puts "############ broadcast start.......... " | |||
| puts "############ broadcast channel_name: channel_room_#{project.id}" | |||
| puts "############ broadcast project data: #{json_data} " | |||
| cable_result = ActionCable.server.broadcast "channel_room_#{project.id}", project: json_data | |||
| puts "############ broadcast result: #{cable_result == 1 ? 'successed' : 'failed'} " | |||
| puts "############ broadcast result: #{cable_result > 0 ? 'successed' : 'failed'} " | |||
| return cable_result | |||
| end | |||
| end | |||
| @@ -0,0 +1,11 @@ | |||
| class DelayExpiredIssueJob < ApplicationJob | |||
| queue_as :message | |||
| def perform | |||
| Issue.where(due_date: Date.today + 1.days).find_each do |issue| | |||
| SendTemplateMessageJob.perform_later('IssueAssignerExpire', issue.id) | |||
| SendTemplateMessageJob.perform_later('IssueCreatorExpire', issue.id) | |||
| end | |||
| end | |||
| end | |||
| @@ -16,5 +16,6 @@ class MigrateRemoteRepositoryJob < ApplicationJob | |||
| else | |||
| repo&.mirror&.failed! | |||
| end | |||
| BroadcastMirrorRepoMsgJob.perform_later(repo.id) unless repo&.mirror.waiting? | |||
| end | |||
| end | |||
| @@ -0,0 +1,259 @@ | |||
| class SendTemplateMessageJob < ApplicationJob | |||
| queue_as :message | |||
| def perform(source, *args) | |||
| Rails.logger.info "SendTemplateMessageJob [args] #{args}" | |||
| case source | |||
| when 'FollowTip' | |||
| watcher_id = args[0] | |||
| watcher = Watcher.find_by_id(watcher_id) | |||
| return unless watcher.present? | |||
| receivers = User.where(id: watcher.watchable_id) | |||
| followeder = User.find_by_id(watcher.user_id) | |||
| receivers_string, content, notification_url = MessageTemplate::FollowedTip.get_message_content(receivers, followeder) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {watcher_id: watcher.id}) | |||
| when 'IssueAssigned' | |||
| operator_id, issue_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? | |||
| receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueAssigned.get_message_content(receivers, operator, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::IssueAssigned.get_email_message_content(receiver, operator, issue) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'IssueAssignerExpire' | |||
| issue_id = args[0] | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless issue.present? | |||
| receivers = User.where(id: issue&.assigned_to_id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueAssignerExpire.get_message_content(receivers, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id}) | |||
| when 'IssueAtme' | |||
| receivers, operator_id, issue_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? | |||
| receivers = receivers.where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueAtme.get_message_content(receivers, operator, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}, 2) | |||
| when 'IssueChanged' | |||
| operator_id, issue_id, change_params = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? | |||
| receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueChanged.get_message_content(receivers, operator, issue, change_params) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id, change_params: change_params.symbolize_keys}) | |||
| when 'IssueCreatorExpire' | |||
| issue_id = args[0] | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless issue.present? | |||
| receivers = User.where(id: issue&.author_id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueCreatorExpire.get_message_content(receivers, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id}) | |||
| when 'IssueDeleted' | |||
| operator_id, issue_title, issue_assigned_to_id, issue_author_id = args[0], args[1], args[2], args[3] | |||
| operator = User.find_by_id(operator_id) | |||
| return unless operator.present? | |||
| receivers = User.where(id: [issue_assigned_to_id, issue_author_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::IssueDeleted.get_message_content(receivers, operator, issue_title) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_title: issue_title}) | |||
| when 'OrganizationJoined' | |||
| user_id, organization_id = args[0], args[1] | |||
| user = User.find_by_id(user_id) | |||
| organization = Organization.find_by_id(organization_id) | |||
| return unless user.present? && organization.present? | |||
| receivers = User.where(id: user.id) | |||
| receivers_string, content, notification_url = MessageTemplate::OrganizationJoined.get_message_content(receivers, organization) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::OrganizationJoined.get_email_message_content(receiver, organization) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'OrganizationLeft' | |||
| user_id, organization_id = args[0], args[1] | |||
| user = User.find_by_id(user_id) | |||
| organization = Organization.find_by_id(organization_id) | |||
| return unless user.present? && organization.present? | |||
| receivers = User.where(id: user.id) | |||
| receivers_string, content, notification_url = MessageTemplate::OrganizationLeft.get_message_content(receivers, organization) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::OrganizationLeft.get_email_message_content(receiver, organization) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'OrganizationRole' | |||
| user_id, organization_id, role = args[0], args[1], args[2] | |||
| user = User.find_by_id(user_id) | |||
| organization = Organization.find_by_id(organization_id) | |||
| return unless user.present? && organization.present? | |||
| receivers = User.where(id: user.id) | |||
| receivers_string, content, notification_url = MessageTemplate::OrganizationRole.get_message_content(receivers, organization, role) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, role: role}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::OrganizationRole.get_email_message_content(receiver, organization, role) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectIssue' | |||
| operator_id, issue_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| issue = Issue.find_by_id(issue_id) | |||
| return unless operator.present? && issue.present? && issue&.project.present? | |||
| managers = issue&.project&.all_managers.where.not(id: operator&.id) | |||
| followers = User.none # TODO | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectIssue.get_message_content(managers, followers, operator, issue) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, issue_id: issue.id}) | |||
| managers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectIssue.get_email_message_content(receiver, true, operator, issue) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| followers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectIssue.get_email_message_content(receiver, false, operator, issue) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectJoined' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = User.where(id: user.id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectJoined.get_message_content(receivers, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectJoined.get_email_message_content(receiver, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectLeft' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = User.where(id: user.id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectLeft.get_message_content(receivers, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectLeft.get_email_message_content(receiver, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectMemberJoined' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = project&.all_managers.where.not(id: [operator&.id, user&.id]) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectMemberJoined.get_message_content(receivers, user, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberJoined.get_email_message_content(receiver, user, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectMemberLeft' | |||
| operator_id, user_id, project_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = project&.all_managers.where.not(id: [operator&.id, user&.id]) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectMemberLeft.get_message_content(receivers, user, project) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectMemberLeft.get_email_message_content(receiver, user, project) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectPullRequest' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? && pull_request&.project.present? | |||
| managers = pull_request&.project&.all_managers.where.not(id: operator&.id) | |||
| followers = User.none # TODO | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectPullRequest.get_message_content(managers, followers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| managers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectPullRequest.get_email_message_content(receiver, true, operator, pull_request) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| followers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectPullRequest.get_email_message_content(receiver, false, operator, pull_request) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectRole' | |||
| operator_id, user_id, project_id, role = args[0], args[1], args[2], args[3] | |||
| operator = User.find_by_id(operator_id) | |||
| user = User.find_by_id(user_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && user.present? && project.present? | |||
| receivers = User.where(id: user.id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectRole.get_message_content(receivers, project, role) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, user_id: user.id, project_id: project.id, role: role}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectRole.get_email_message_content(receivers, project, role) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'ProjectSettingChanged' | |||
| operator_id, project_id, change_params = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| project = Project.find_by_id(project_id) | |||
| return unless operator.present? && project.present? | |||
| receivers = project.all_managers.where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::ProjectSettingChanged.get_message_content(receivers, operator, project, change_params.symbolize_keys) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, project_id: project.id, change_params: change_params}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::ProjectSettingChanged.get_email_message_content(receiver, operator, project, change_params.symbolize_keys) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'PullRequestAssigned' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| issue = Issue.find_by_id(pull_request&.issue_id) | |||
| return unless operator.present? && pull_request.present? && issue.present? | |||
| receivers = User.where(id: issue&.assigned_to_id).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestAssigned.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| receivers.find_each do |receiver| | |||
| receivers_email_string, email_title, email_content = MessageTemplate::PullRequestAssigned.get_email_message_content(receiver, operator, pull_request) | |||
| Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content) | |||
| end | |||
| when 'PullRequestAtme' | |||
| receivers, operator_id, pull_request_id = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? | |||
| receivers = receivers.where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestAtme.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}, 2) | |||
| when 'PullRequestChanged' | |||
| operator_id, pull_request_id, change_params = args[0], args[1], args[2] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| issue = Issue.find_by_id(pull_request&.issue_id) | |||
| return unless operator.present? && pull_request.present? && issue.present? | |||
| receivers = User.where(id: [issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestChanged.get_message_content(receivers, operator, pull_request, change_params.symbolize_keys) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id, change_params: change_params}) | |||
| when 'PullRequestClosed' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? | |||
| receivers = User.where(id: [pull_request&.issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestClosed.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| when 'PullRequestMerged' | |||
| operator_id, pull_request_id = args[0], args[1] | |||
| operator = User.find_by_id(operator_id) | |||
| pull_request = PullRequest.find_by_id(pull_request_id) | |||
| return unless operator.present? && pull_request.present? | |||
| receivers = User.where(id: [pull_request&.issue&.assigned_to_id, pull_request&.user_id]).where.not(id: operator&.id) | |||
| receivers_string, content, notification_url = MessageTemplate::PullRequestMerged.get_message_content(receivers, operator, pull_request) | |||
| Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {operator_id: operator.id, pull_request_id: pull_request.id}) | |||
| end | |||
| end | |||
| end | |||
| @@ -26,6 +26,7 @@ class SyncMirroredRepositoryJob < ApplicationJob | |||
| result = Gitea::Repository::SyncMirroredService.call(repo.owner.login, | |||
| repo.identifier, token: user.gitea_token) | |||
| repo&.mirror.set_status! if result[:status] === 200 | |||
| BroadcastMirrorRepoMsgJob.perform_later(repo.id) unless repo&.mirror.waiting? | |||
| end | |||
| end | |||
| @@ -0,0 +1,21 @@ | |||
| module Notice | |||
| class << self | |||
| def notice_config | |||
| notice_config = {} | |||
| begin | |||
| config = Rails.application.config_for(:configuration).symbolize_keys! | |||
| notice_config = config[:notice].symbolize_keys! | |||
| raise 'notice config missing' if notice_config.blank? | |||
| rescue => exception | |||
| raise ex if Rails.env.production? | |||
| puts %Q{\033[33m [warning] gitea config or configuration.yml missing, | |||
| please add it or execute 'cp config/configuration.yml.example config/configuration.yml' \033[0m} | |||
| notice_config = {} | |||
| end | |||
| notice_config | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,99 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| class MessageTemplate < ApplicationRecord | |||
| def self.build_init_data | |||
| self.create(type: 'MessageTemplate::FollowedTip', sys_notice: '<b>{nickname}</b> 关注了你', notification_url: '{baseurl}/{login}') | |||
| email_html = File.read("#{email_template_html_dir}/issue_assigned.html") | |||
| self.create(type: 'MessageTemplate::IssueAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个易修') | |||
| self.create(type: 'MessageTemplate::IssueAssignerExpire', sys_notice: '您负责的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueAtme', sys_notice: '<b>{nickname}</b> 在易修 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueChanged', sys_notice: '在项目 <b>{nickname2}/{repository}</b> 的易修 <b>{title}</b> 中:{ifassigner}{nickname1}将负责人从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifstatus}{nickname1}将状态从 <b>{status1}</b> 修改为 <b>{status2}</b> {endstatus}{iftracker}{nickname1}将类型从 <b>{tracker1}</b> 修改为 <b>{tracker2}</b> {endtracker}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifdoneratio}{nickname1}将完成度从 <b>{doneratio1}</b> 修改为 <b>{doneratio2}</b> {enddoneratio}{ifbranch}{nickname1}将指定分支从 <b>{branch1}</b> 修改为 <b>{branch2}</b> {endbranch}{ifstartdate}{nickname1}将开始日期从 <b>{startdate1}</b> 修改为 <b>{startdate2}</b> {endstartdate}{ifduedate}{nickname1}将结束日期从 <b>{duedate1}</b> 修改为 <b>{duedate2}</b> {endduedate}', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueCreatorExpire', sys_notice: '您发布的易修 <b>{title}</b> 已临近截止日期,请尽快处理', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::IssueDeleted', sys_notice: '{nickname}已将易修 <b>{title}</b> 删除', notification_url: '') | |||
| self.create(type: 'MessageTemplate::IssueJournal', sys_notice: '{nickname}评论易修{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}') | |||
| self.create(type: 'MessageTemplate::LoginIpTip', sys_notice: '您的账号{nickname}于{login_time)在非常用的IP地址{ip}登录,如非本人操作,请立即修改密码', notification_url: '') | |||
| email_html = File.read("#{email_template_html_dir}/organization_joined.html") | |||
| self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: '你已加入 {organization} 组织') | |||
| email_html = File.read("#{email_template_html_dir}/organization_left.html") | |||
| self.create(type: 'MessageTemplate::OrganizationLeft', sys_notice: '你已被移出 <b>{organization}</b> 组织', notification_url: '', email: email_html, email_title: '你已被移出 {organization} 组织') | |||
| self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', notification_url: '{baseurl}/{login}') | |||
| self.create(type: 'MessageTemplate::ProjectDeleted', sys_notice: '你关注的仓库{nickname}/{repository}已被删除', notification_url: '') | |||
| self.create(type: 'MessageTemplate::ProjectFollowed', sys_notice: '<b>{nickname}</b> 关注了你管理的仓库', notification_url: '{baseurl}/{login}') | |||
| self.create(type: 'MessageTemplate::ProjectForked', sys_notice: '<b>{nickname1}</b> 复刻了你管理的仓库{nickname1}/{repository1}到{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') | |||
| email_html = File.read("#{email_template_html_dir}/project_issue.html") | |||
| self.create(type: 'MessageTemplate::ProjectIssue', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 新建易修:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/issues/{id}', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 新建了一个易修') | |||
| email_html = File.read("#{email_template_html_dir}/project_joined.html") | |||
| self.create(type: 'MessageTemplate::ProjectJoined', sys_notice: '你已加入 <b>{repository}</b> 项目', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '你已加入 {repository} 项目') | |||
| email_html = File.read("#{email_template_html_dir}/project_left.html") | |||
| self.create(type: 'MessageTemplate::ProjectLeft', sys_notice: '你已被移出 <b>{repository}</b> 项目', notification_url: '', email: email_html, email_title: '你已被移出 {repository} 项目') | |||
| email_html = File.read("#{email_template_html_dir}/project_member_joined.html") | |||
| self.create(type: 'MessageTemplate::ProjectMemberJoined', sys_notice: '<b>{nickname1}</b> 已加入项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已加入项目 {nickname2}/{repository}') | |||
| email_html = File.read("#{email_template_html_dir}/project_member_left.html") | |||
| self.create(type: 'MessageTemplate::ProjectMemberLeft', sys_notice: '<b>{nickname1}</b> 已被移出项目 <b>{nickname2}/{repository}</b>', notification_url: '{baseurl}/{owner}/{identifier}', email: email_html, email_title: '{nickname1} 已被移出项目 {nickname2}/{repository}') | |||
| self.create(type: 'MessageTemplate::ProjectMilestone', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了一个里程碑:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/milestones/{id}') | |||
| self.create(type: 'MessageTemplate::ProjectPraised', sys_notice: '<b>{nickname}</b> 点赞了你管理的仓库', notification_url: '{baseurl}/{login}') | |||
| email_html = File.read("#{email_template_html_dir}/project_pull_request.html") | |||
| self.create(type: 'MessageTemplate::ProjectPullRequest', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 提交了一个合并请求:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 提交了一个合并请求') | |||
| self.create(type: 'MessageTemplate::ProjectRole', sys_notice: '仓库 <b>{repository}</b> 已把你的角色改为 <b>{role}</b>', notification_url: '{baseurl}/{owner}/{identifier}') | |||
| email_html = File.read("#{email_template_html_dir}/project_setting_changed.html") | |||
| self.create(type: 'MessageTemplate::ProjectSettingChanged', sys_notice: '{nickname1}更改了 <b>{nickname2}/{repository}</b> 仓库设置:{ifname}更改项目名称为"<b>{name}</b>"{endname}{ifdescription}更改项目简介为"<b>{description}</b>"{enddescription}{ifcategory}更改项目类别为"<b>{category}</b>"{endcategory}{iflanguage}更改项目语言为"<b>{language}</b>"{endlanguage}{ifpermission}将仓库设为"<b>{permission}</b>"{endpermission}{ifnavbar}将项目导航更改为"<b>{navbar}</b>"{endnavbar}', notification_url: '{baseurl}/{owner}/{identifier}/settings', email: email_html, email_title: '您管理的仓库 {nickname2}/{repository} 仓库设置已被更改') | |||
| self.create(type: 'MessageTemplate::ProjectTransfer', sys_notice: '你关注的仓库{nickname1}/{repository1}已被转移至{nickname2}/{repository2}', notification_url: '{baseurl}/{owner}/{identifier}') | |||
| self.create(type: 'MessageTemplate::ProjectVersion', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 创建了发行版:<b>{title}</b>', notification_url: '{baseurl}/{owner}/{identifier}/releases') | |||
| email_html = File.read("#{email_template_html_dir}/pull_request_assigned.html") | |||
| self.create(type: 'MessageTemplate::PullRequestAssigned', sys_notice: '{nickname1}在 <b>{nickname2}/{repository}</b> 指派给你一个合并请求:<b>{title}<b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount', email: email_html, email_title: '{nickname1} 在 {nickname2}/{repository} 指派给你一个合并请求') | |||
| self.create(type: 'MessageTemplate::PullRequestAtme', sys_notice: '<b>{nickname}</b> 在合并请求 <b>{title}</b> 中@我', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| self.create(type: 'MessageTemplate::PullRequestChanged', sys_notice: '在项目{nickname2}/{repository}的合并请求 <b>{title}</b> 中:{ifassigner}{nickname1}将审查成员从 <b>{assigner1}</b> 修改为 <b>{assigner2}</b> {endassigner}{ifmilestone}{nickname1}将里程碑从 <b>{milestone1}</b> 修改为 <b>{milestone2}</b> {endmilestone}{iftag}{nickname1}将标记从 <b>{tag1}</b> 修改为 <b>{tag2}</b> {endtag}{ifpriority}{nickname1}将优先级从 <b>{priority1}</b> 修改为 <b>{priority2}</b> {endpriority}', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| self.create(type: 'MessageTemplate::PullRequestClosed', sys_notice: '你提交的合并请求:{title} <b>被拒绝</b>', notification_url: '') | |||
| self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}:<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}/Messagecount') | |||
| end | |||
| def self.sys_notice | |||
| self.last&.sys_notice | |||
| end | |||
| def self.email | |||
| self.last&.email | |||
| end | |||
| def self.email_title | |||
| self.last&.email_title | |||
| end | |||
| def self.notification_url | |||
| self.last&.notification_url.gsub('{baseurl}', base_url) | |||
| end | |||
| def self.base_url | |||
| Rails.application.config_for(:configuration)['platform_url'] | |||
| end | |||
| def self.receivers_string(receivers) | |||
| receivers.pluck(:id).join(",") | |||
| end | |||
| def self.receivers_email_string(receivers) | |||
| receivers.pluck(:mail).join(",") | |||
| end | |||
| def self.email_template_html_dir | |||
| "#{Rails.root}/public/message_template" | |||
| end | |||
| def simple_type | |||
| self.type.split("::")[-1] | |||
| end | |||
| end | |||
| @@ -0,0 +1,24 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 被关注提示 | |||
| class MessageTemplate::FollowedTip < MessageTemplate | |||
| # MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last) | |||
| def self.get_message_content(receivers, followeder) | |||
| return receivers_string(receivers), sys_notice.gsub('{nickname}', followeder&.real_name), notification_url.gsub('{login}', followeder.login) | |||
| rescue | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,54 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 有新指派给我的易修 | |||
| class MessageTemplate::IssueAssigned < MessageTemplate | |||
| # MessageTemplate::IssueAssigned.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last) | |||
| def self.get_message_content(receivers, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{title}', issue&.subject) | |||
| content.gsub!('{id}', issue&.id.to_s) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssigned.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我负责的易修截止日期到达最后一天 | |||
| class MessageTemplate::IssueAssignerExpire < MessageTemplate | |||
| # MessageTemplate::IssueAssignerExpire.get_message_content(User.where(login: 'yystopf'), Issue.last) | |||
| def self.get_message_content(receivers, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 在易修中@我 | |||
| class MessageTemplate::IssueAtme < MessageTemplate | |||
| # MessageTemplate::IssueAtme.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last) | |||
| def self.get_message_content(receivers, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAtme.get_message_content [ERROR] #{e}") | |||
| return 0, '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,183 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我创建或负责的易修状态变更 | |||
| class MessageTemplate::IssueChanged < MessageTemplate | |||
| # MessageTemplate::IssueChanged.get_message_content(User.where(login: 'yystopf'), User.last, Issue.last, {status_id: [1, 2], assigned_to_id: [nil, 203], tracker_id: [4, 3], priority_id: [2, 4], fixed_version_id: [nil, 5], due_date: ['', '2021-09-11'], done_ratio: [0, 40], issue_tags_value: ["", "7"], branch_name: ["", "master"]}) | |||
| def self.get_message_content(receivers, operator, issue, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = MessageTemplate::IssueChanged.sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| change_count = change_params.keys.size | |||
| # 易修负责人修改 | |||
| if change_params[:assigned_to_id].present? | |||
| assigner1 = User.find_by_id(change_params[:assigned_to_id][0]) | |||
| assigner2 = User.find_by_id(change_params[:assigned_to_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifassigner}', '<br/>') | |||
| else | |||
| content.sub!('{ifassigner}', '') | |||
| end | |||
| content.sub!('{endassigner}', '') | |||
| content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员') | |||
| content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员') | |||
| else | |||
| content.gsub!(/({ifassigner})(.*)({endassigner})/, '') | |||
| end | |||
| # 易修状态修改 | |||
| if change_params[:status_id].present? | |||
| status1 = IssueStatus.find_by_id(change_params[:status_id][0]) | |||
| status2 = IssueStatus.find_by_id(change_params[:status_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifstatus}', '<br/>') | |||
| else | |||
| content.sub!('{ifstatus}', '') | |||
| end | |||
| content.sub!('{endstatus}', '') | |||
| content.gsub!('{status1}', status1&.name) | |||
| content.gsub!('{status2}', status2&.name) | |||
| else | |||
| content.gsub!(/({ifstatus})(.*)({endstatus})/, '') | |||
| end | |||
| # 易修类型修改 | |||
| if change_params[:tracker_id].present? | |||
| tracker1 = Tracker.find_by_id(change_params[:tracker_id][0]) | |||
| tracker2 = Tracker.find_by_id(change_params[:tracker_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{iftracker}', '<br/>') | |||
| else | |||
| content.sub!('{iftracker}', '') | |||
| end | |||
| content.sub!('{endtracker}', '') | |||
| content.gsub!('{tracker1}', tracker1&.name) | |||
| content.gsub!('{tracker2}', tracker2&.name) | |||
| else | |||
| content.gsub!(/({iftracker})(.*)({endtracker})/, '') | |||
| end | |||
| # 易修里程碑修改 | |||
| if change_params[:fixed_version_id].present? | |||
| fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0]) | |||
| fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifmilestone}', '<br/>') | |||
| else | |||
| content.sub!('{ifmilestone}', '') | |||
| end | |||
| content.sub!('{endmilestone}', '') | |||
| content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑') | |||
| content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑') | |||
| else | |||
| content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '') | |||
| end | |||
| # 易修标记修改 | |||
| if change_params[:issue_tags_value].present? | |||
| issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct | |||
| issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct | |||
| tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",") | |||
| tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",") | |||
| if change_count > 1 | |||
| content.sub!('{iftag}', '<br/>') | |||
| else | |||
| content.sub!('{iftag}', '') | |||
| end | |||
| content.sub!('{endtag}', '') | |||
| content.gsub!('{tag1}', tag1) | |||
| content.gsub!('{tag2}', tag2) | |||
| else | |||
| content.gsub!(/({iftag})(.*)({endtag})()/, '') | |||
| end | |||
| # 易修优先级修改 | |||
| if change_params[:priority_id].present? | |||
| priority1 = IssuePriority.find_by_id(change_params[:priority_id][0]) | |||
| priority2 = IssuePriority.find_by_id(change_params[:priority_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifpriority}', '<br/>') | |||
| else | |||
| content.sub!('{ifpriority}', '') | |||
| end | |||
| content.sub!('{endpriority}', '') | |||
| content.gsub!('{priority1}', priority1&.name) | |||
| content.gsub!('{priority2}', priority2&.name) | |||
| else | |||
| content.gsub!(/({ifpriority})(.*)({endpriority})/, '') | |||
| end | |||
| # 易修完成度修改 | |||
| if change_params[:done_ratio].present? | |||
| doneratio1 = change_params[:done_ratio][0] | |||
| doneratio2 = change_params[:done_ratio][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifdoneratio}', '<br/>') | |||
| else | |||
| content.sub!('{ifdoneratio}', '') | |||
| end | |||
| content.sub!('{enddoneratio}', '') | |||
| content.gsub!('{doneratio1}', "#{doneratio1}%") | |||
| content.gsub!('{doneratio2}', "#{doneratio2}%") | |||
| else | |||
| content.gsub!(/({ifdoneratio})(.*)({enddoneratio})/, '') | |||
| end | |||
| # 易修指定分支修改 | |||
| if change_params[:branch_name].present? | |||
| branch1 = change_params[:branch_name][0].blank? ? '分支未指定' : change_params[:branch_name][0] | |||
| branch2 = change_params[:branch_name][1].blank? ? '分支未指定' : change_params[:branch_name][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifbranch}', '<br/>') | |||
| else | |||
| content.sub!('{ifbranch}', '') | |||
| end | |||
| content.sub!('{endbranch}', '') | |||
| content.gsub!('{branch1}', branch1) | |||
| content.gsub!('{branch2}', branch2) | |||
| else | |||
| content.gsub!(/({ifbranch})(.*)({endbranch})/, '') | |||
| end | |||
| # 易修开始日期修改 | |||
| if change_params[:start_date].present? | |||
| startdate1 = change_params[:start_date][0].blank? ? "未选择开始日期" : change_params[:start_date][0] | |||
| startdate2 = change_params[:start_date][1].blank? ? "未选择开始日期" : change_params[:start_date][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifstartdate}', '<br/>') | |||
| else | |||
| content.sub!('{ifstartdate}', '') | |||
| end | |||
| content.sub!('{endstartdate}', '') | |||
| content.gsub!('{startdate1}', startdate1 ) | |||
| content.gsub!('{startdate2}', startdate2) | |||
| else | |||
| content.gsub!(/({ifstartdate})(.*)({endstartdate})/, '') | |||
| end | |||
| # 易修结束日期修改 | |||
| if change_params[:due_date].present? | |||
| duedate1 = change_params[:due_date][0].blank? ? '未选择结束日期' : change_params[:due_date][0] | |||
| duedate2 = change_params[:due_date][1].blank? ? '未选择结束日期' : change_params[:due_date][1] | |||
| if change_count > 1 | |||
| content.sub!('{ifduedate}', '<br/>') | |||
| else | |||
| content.sub!('{ifduedate}', '') | |||
| end | |||
| content.sub!('{endduedate}', '') | |||
| content.gsub!('{duedate1}', duedate1) | |||
| content.gsub!('{duedate2}', duedate2) | |||
| else | |||
| content.gsub!(/({ifduedate})(.*)({endduedate})/, '') | |||
| end | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssigned.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我创建的易修截止日期到达最后一天 | |||
| class MessageTemplate::IssueCreatorExpire < MessageTemplate | |||
| # MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last) | |||
| def self.get_message_content(receivers, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAssignerExpire.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,26 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我创建或负责的易修删除 | |||
| class MessageTemplate::IssueDeleted < MessageTemplate | |||
| # MessageTemplate::IssueDeleted.get_message_content(User.where(login: 'yystopf'), User.last, "hahah") | |||
| def self.get_message_content(receivers, operator, issue_title) | |||
| content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', issue_title) | |||
| return receivers_string(receivers), content, notification_url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueAtme.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我创建或负责的易修有新的评论 | |||
| class MessageTemplate::IssueJournal < MessageTemplate | |||
| # MessageTemplate::IssueJournal.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::IssueJournal.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 登录异常提示 | |||
| class MessageTemplate::LoginIpTip < MessageTemplate | |||
| # MessageTemplate::LoginIpTip.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::LoginIpTip.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 账号被拉入组织 | |||
| class MessageTemplate::OrganizationJoined < MessageTemplate | |||
| # MessageTemplate::OrganizationJoined.get_message_content(User.where(login: 'yystopf'), Organization.last) | |||
| def self.get_message_content(receivers, organization) | |||
| content = sys_notice.gsub('{organization}', organization&.real_name) | |||
| url = notification_url.gsub('{login}', organization&.name) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationJoined.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, organization) | |||
| title = email_title | |||
| title.gsub!('{organization}', organization&.real_name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', organization&.login) | |||
| content.gsub!('{organization}', organization&.real_name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationJoined.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 账号被移出组织 | |||
| class MessageTemplate::OrganizationLeft < MessageTemplate | |||
| # MessageTemplate::OrganizationLeft.get_message_content(User.where(login: 'yystopf'), Organization.last) | |||
| def self.get_message_content(receivers, organization) | |||
| content = sys_notice.gsub('{organization}', organization&.real_name) | |||
| url = notification_url.gsub('{login}', organization&.name) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationLeft.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, organization) | |||
| title = email_title | |||
| title.gsub!('{organization}', organization&.real_name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', organization&.login) | |||
| content.gsub!('{organization}', organization&.real_name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationLeft.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,44 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 账号组织权限变更 | |||
| class MessageTemplate::OrganizationRole < MessageTemplate | |||
| # MessageTemplate::OrganizationRole.get_message_content(User.where(login: 'yystopf'), Organization.last, '管理员') | |||
| def self.get_message_content(receivers, organization, role) | |||
| content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{role}', role) | |||
| url = notification_url.gsub('{login}', organization&.login) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationRole.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, organization, role) | |||
| title = email_title | |||
| title.gsub!('{organization}', organization&.real_name) | |||
| title.gsub!('{role}', role) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', organization&.login) | |||
| content.gsub!('{organization}', organization&.real_name) | |||
| content.gsub!('{role}', role) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::OrganizationRole.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我关注的仓库被删除 | |||
| class MessageTemplate::ProjectDeleted < MessageTemplate | |||
| # MessageTemplate::ProjectDeleted.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectDeleted.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我管理的仓库被关注 | |||
| class MessageTemplate::ProjectFollowed < MessageTemplate | |||
| # MessageTemplate::ProjectFollowed.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectFollowed.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我管理的仓库被复刻 | |||
| class MessageTemplate::ProjectForked < MessageTemplate | |||
| # MessageTemplate::ProjectForked.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectForked.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,57 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我管理/关注的仓库有新的易修 | |||
| class MessageTemplate::ProjectIssue < MessageTemplate | |||
| # MessageTemplate::ProjectIssue.get_message_content(User.where(login: 'yystopf'), User.where(login: 'forgetest1'), User.last, Issue.last) | |||
| def self.get_message_content(managers, followers, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| receivers = managers + followers | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', issue&.subject) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', issue&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectIssue.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, is_manager, operator, issue) | |||
| project = issue&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{id}', issue&.id.to_s) | |||
| content.gsub!('{title}', issue&.subject) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectIssue.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,45 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 账号被拉入项目 | |||
| class MessageTemplate::ProjectJoined < MessageTemplate | |||
| # MessageTemplate::ProjectJoined.get_message_content(User.where(login: 'yystopf'), Project.last) | |||
| def self.get_message_content(receivers, project) | |||
| content = sys_notice.gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectJoined.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, project) | |||
| title = email_title | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectJoined.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,45 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 账号被移出项目 | |||
| class MessageTemplate::ProjectLeft < MessageTemplate | |||
| # MessageTemplate::ProjectLeft.get_message_content(User.where(login: 'yystopf'), Project.last) | |||
| def self.get_message_content(receivers, project) | |||
| content = sys_notice.gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectLeft.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, project) | |||
| title = email_title | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectLeft.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,49 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我管理的仓库有成员加入 | |||
| class MessageTemplate::ProjectMemberJoined < MessageTemplate | |||
| # MessageTemplate::ProjectMemberJoined.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers, user, project) | |||
| content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberJoined.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, user, project) | |||
| title = email_title | |||
| title.gsub!('{nickname1}', user&.real_name) | |||
| title.gsub!('{nickname2}', project&.owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', user&.login) | |||
| content.gsub!('{login2}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname1}', user&.real_name) | |||
| content.gsub!('{nickname2}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberJoined.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,49 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我管理的仓库有成员移出 | |||
| class MessageTemplate::ProjectMemberLeft < MessageTemplate | |||
| # MessageTemplate::ProjectMemberLeft.get_message_content(User.where(login: 'yystopf'), User.last, Project.last) | |||
| def self.get_message_content(receivers, user, project) | |||
| content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberLeft.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, user, project) | |||
| title = email_title | |||
| title.gsub!('{nickname1}', user&.real_name) | |||
| title.gsub!('{nickname2}', project&.owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', user&.login) | |||
| content.gsub!('{login2}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{nickname1}', user&.real_name) | |||
| content.gsub!('{nickname2}', project&.owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMemberLeft.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我管理的仓库有新的里程碑 | |||
| class MessageTemplate::ProjectMilestone < MessageTemplate | |||
| # MessageTemplate::ProjectMilestone.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectMilestone.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我管理的仓库被点赞 | |||
| class MessageTemplate::ProjectPraised < MessageTemplate | |||
| # MessageTemplate::ProjectPraised.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectPraised.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,57 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我管理/关注的仓库有新的合并请求 | |||
| class MessageTemplate::ProjectPullRequest < MessageTemplate | |||
| # MessageTemplate::ProjectPullRequest.get_message_content(User.where(login: 'yystopf'), User.where(login: 'testforge2'), User.last, PullRequest.last) | |||
| def self.get_message_content(managers, followers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| receivers = managers + followers | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectPullRequest.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, is_manager, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{id}', pull_request&.id.to_s) | |||
| content.gsub!('{title}', pull_request&.title) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectPullRequest.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,45 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 账号仓库权限变更 | |||
| class MessageTemplate::ProjectRole < MessageTemplate | |||
| # MessageTemplate::ProjectRole.get_message_content(User.where(login: 'yystopf'), Project.last, '管理员') | |||
| def self.get_message_content(receivers, project, role) | |||
| content = sys_notice.gsub('{repository}', project&.name).gsub('{role}', role) | |||
| url = notification_url.gsub('{owner}', project&.owner&.login).gsub('{identifier}', project&.identifier) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectRole.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receivers, project, role) | |||
| title = email_title | |||
| title.gsub!('{repository}', project&.name) | |||
| title.gsub!('{role}', role) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login}', project&.owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{role}', role) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectRole.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,277 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我管理的仓库项目设置被更改 | |||
| class MessageTemplate::ProjectSettingChanged < MessageTemplate | |||
| # MessageTemplate::ProjectSettingChanged.get_message_content(User.where(login: 'yystopf'), User.last, Project.last, {description: '测试修改项目简介', category: '大数据', language: 'Ruby', permission: '公有', navbar: '易修, 合并请求'}) | |||
| def self.get_message_content(receivers, operator, project, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier) | |||
| change_count = change_params.keys.size | |||
| # 项目名称更改 | |||
| if change_params[:name].present? | |||
| if change_count > 1 | |||
| content.sub!('{ifname}', '<br/>') | |||
| else | |||
| content.sub!('{ifname}', '') | |||
| end | |||
| content.sub!('{endname}', '') | |||
| content.gsub!('{name}', change_params[:name][1]) | |||
| else | |||
| content.gsub!(/({ifname})(.*)({endname})/, '') | |||
| end | |||
| # 项目简介更改 | |||
| if change_params[:description].present? | |||
| if change_params[:description][1].blank? | |||
| if change_count > 1 | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '<br/>删除了项目简介') | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '删除了项目简介') | |||
| end | |||
| else | |||
| if change_count > 1 | |||
| content.sub!('{ifdescription}', '<br/>') | |||
| else | |||
| content.sub!('{ifdescription}', '') | |||
| end | |||
| content.sub!('{enddescription}', '') | |||
| content.gsub!('{description}', change_params[:description][1]) | |||
| end | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '') | |||
| end | |||
| # 项目类别更改 | |||
| if change_params[:project_category_id].present? | |||
| category = ProjectCategory.find_by_id(change_params[:project_category_id][1]) | |||
| if category.present? | |||
| if change_count > 1 | |||
| content.sub!('{ifcategory}', '<br/>') | |||
| else | |||
| content.sub!('{ifcategory}', '') | |||
| end | |||
| content.sub!('{endcategory}', '') | |||
| content.gsub!('{category}', category&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '<br/>删除了项目类别') | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '删除了项目类别') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '') | |||
| end | |||
| # 项目语言更改 | |||
| if change_params[:project_language_id].present? | |||
| language = ProjectLanguage.find_by_id(change_params[:project_language_id][1]) | |||
| if language.present? | |||
| if change_count > 1 | |||
| content.sub!('{iflanguage}', '<br/>') | |||
| else | |||
| content.sub!('{iflanguage}', '') | |||
| end | |||
| content.sub!('{endlanguage}', '') | |||
| content.gsub!('{language}', language&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '<br/>删除了项目语言') | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '删除了项目语言') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '') | |||
| end | |||
| # 项目公私有更改 | |||
| if change_params[:is_public].present? | |||
| permission = change_params[:is_public][1] ? '公有' : '私有' | |||
| if change_count > 1 | |||
| content.sub!('{ifpermission}', '<br/>') | |||
| else | |||
| content.sub!('{ifpermission}', '') | |||
| end | |||
| content.sub!('{endpermission}', '') | |||
| content.gsub!('{permission}', permission) | |||
| else | |||
| content.gsub!(/({ifpermission})(.*)({endpermission})/, '') | |||
| end | |||
| # 项目导航更改 | |||
| if change_params[:navbar].present? | |||
| unit_types = project.project_units.order(unit_type: :asc).pluck(:unit_type) | |||
| unit_types.delete('code') | |||
| unit_types.unshift('代码库') | |||
| unit_types.unshift('主页') | |||
| unit_types.append('动态') | |||
| navbar = unit_types.join(',') | |||
| navbar.gsub!('issues', '易修') | |||
| navbar.gsub!('pulls', '合并请求') | |||
| navbar.gsub!('wiki', 'Wiki') | |||
| navbar.gsub!('devops', '工作流') | |||
| navbar.gsub!('versions', '里程碑') | |||
| navbar.gsub!('resources', '资源库') | |||
| if change_count > 1 | |||
| content.sub!('{ifnavbar}', '<br/>') | |||
| else | |||
| content.sub!('{ifnavbar}', '') | |||
| end | |||
| content.sub!('{endnavbar}', '') | |||
| content.gsub!('{navbar}', navbar) | |||
| else | |||
| content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '') | |||
| end | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectSettingChanged.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, operator, project, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| change_count = change_params.keys.size | |||
| # 项目名称更改 | |||
| if change_params[:name].present? | |||
| if change_count > 1 | |||
| content.sub!('{ifname}', '<br/>') | |||
| else | |||
| content.sub!('{ifname}', '') | |||
| end | |||
| content.sub!('{endname}', '') | |||
| content.gsub!('{name}', change_params[:name][1]) | |||
| else | |||
| content.gsub!(/({ifname})(.*)({endname})/, '') | |||
| end | |||
| # 项目简介更改 | |||
| if change_params[:description].present? | |||
| if change_params[:description][1].blank? | |||
| if change_count > 1 | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '<br/>删除了项目简介') | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '删除了项目简介') | |||
| end | |||
| else | |||
| if change_count > 1 | |||
| content.sub!('{ifdescription}', '<br/>') | |||
| else | |||
| content.sub!('{ifdescription}', '') | |||
| end | |||
| content.sub!('{enddescription}', '') | |||
| content.gsub!('{description}', change_params[:description][1]) | |||
| end | |||
| else | |||
| content.gsub!(/({ifdescription})(.*)({enddescription})/, '') | |||
| end | |||
| # 项目类别更改 | |||
| if change_params[:project_category_id].present? | |||
| category = ProjectCategory.find_by_id(change_params[:project_category_id][1]) | |||
| if category.present? | |||
| if change_count > 1 | |||
| content.sub!('{ifcategory}', '<br/>') | |||
| else | |||
| content.sub!('{ifcategory}', '') | |||
| end | |||
| content.sub!('{endcategory}', '') | |||
| content.gsub!('{category}', category&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '<br/>删除了项目类别') | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '删除了项目类别') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({ifcategory})(.*)({endcategory})/, '') | |||
| end | |||
| # 项目语言更改 | |||
| if change_params[:project_language_id].present? | |||
| language = ProjectLanguage.find_by_id(change_params[:project_language_id][1]) | |||
| if language.present? | |||
| if change_count > 1 | |||
| content.sub!('{iflanguage}', '<br/>') | |||
| else | |||
| content.sub!('{iflanguage}', '') | |||
| end | |||
| content.sub!('{endlanguage}', '') | |||
| content.gsub!('{language}', language&.name) | |||
| else | |||
| if change_count > 1 | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '<br/>删除了项目语言') | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '删除了项目语言') | |||
| end | |||
| end | |||
| else | |||
| content.gsub!(/({iflanguage})(.*)({endlanguage})/, '') | |||
| end | |||
| # 项目公私有更改 | |||
| if change_params[:is_public].present? | |||
| permission = change_params[:is_public][1] ? '公有' : '私有' | |||
| if change_count > 1 | |||
| content.sub!('{ifpermission}', '<br/>') | |||
| else | |||
| content.sub!('{ifpermission}', '') | |||
| end | |||
| content.sub!('{endpermission}', '') | |||
| content.gsub!('{permission}', permission) | |||
| else | |||
| content.gsub!(/({ifpermission})(.*)({endpermission})/, '') | |||
| end | |||
| # 项目导航更改 | |||
| if change_params[:navbar].present? | |||
| unit_types = project.project_units.order(unit_type: :asc).pluck(:unit_type) | |||
| unit_types.delete('code') | |||
| unit_types.unshift('代码库') | |||
| unit_types.unshift('主页') | |||
| unit_types.append('动态') | |||
| navbar = unit_types.join(',') | |||
| navbar.gsub!('issues', '易修') | |||
| navbar.gsub!('pulls', '合并请求') | |||
| navbar.gsub!('wiki', 'Wiki') | |||
| navbar.gsub!('devops', '工作流') | |||
| navbar.gsub!('versions', '里程碑') | |||
| navbar.gsub!('resources', '资源库') | |||
| if change_count > 1 | |||
| content.sub!('{ifnavbar}', '<br/>') | |||
| else | |||
| content.sub!('{ifnavbar}', '') | |||
| end | |||
| content.sub!('{endnavbar}', '') | |||
| content.gsub!('{navbar}', navbar) | |||
| else | |||
| content.gsub!(/({ifnavbar})(.*)({endnavbar})/, '') | |||
| end | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectSettingChanged.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我关注的仓库被转移 | |||
| class MessageTemplate::ProjectTransfer < MessageTemplate | |||
| # MessageTemplate::ProjectTransfer.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectTransfer.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我关注的仓库有新的发行版 | |||
| class MessageTemplate::ProjectVersion < MessageTemplate | |||
| # MessageTemplate::ProjectVersion.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::ProjectVersion.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,54 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 有新指派给我的合并请求 | |||
| class MessageTemplate::PullRequestAssigned < MessageTemplate | |||
| # MessageTemplate::PullRequestAssigned.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestAssigned.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| def self.get_email_message_content(receiver, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| title = email_title | |||
| title.gsub!('{nickname1}', operator&.real_name) | |||
| title.gsub!('{nickname2}', owner&.real_name) | |||
| title.gsub!('{repository}', project&.name) | |||
| content = email | |||
| content.gsub!('{receiver}', receiver&.real_name) | |||
| content.gsub!('{nickname1}', operator&.real_name) | |||
| content.gsub!('{login1}', operator&.login) | |||
| content.gsub!('{nickname2}', owner&.real_name) | |||
| content.gsub!('{login2}', owner&.login) | |||
| content.gsub!('{identifier}', project&.identifier) | |||
| content.gsub!('{repository}', project&.name) | |||
| content.gsub!('{baseurl}', base_url) | |||
| content.gsub!('{title}', pull_request&.title) | |||
| content.gsub!('{id}', pull_request&.id.to_s) | |||
| return receiver&.mail, title, content | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestAssigned.get_email_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 在合并请求中@我 | |||
| class MessageTemplate::PullRequestAtme < MessageTemplate | |||
| # MessageTemplate::PullRequestAtme.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{nickname}', operator&.real_name).gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestAtme.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,95 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我创建或负责的合并请求状态变更 | |||
| class MessageTemplate::PullRequestChanged < MessageTemplate | |||
| # MessageTemplate::PullRequestChanged.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last, {assigned_to_id: [nil, 203], priority_id: [2, 4], fixed_version_id: [nil, 5], issue_tags_value: ["", "7"]}) | |||
| def self.get_message_content(receivers, operator, pull_request, change_params) | |||
| return '', '', '' if change_params.blank? | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| issue = pull_request&.issue | |||
| content = sys_notice.gsub('{nickname1}', operator&.real_name).gsub('{nickname2}', owner&.real_name).gsub('{repository}', project&.name).gsub("{title}", pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| change_count = change_params.keys.size | |||
| # 合并请求审查成员修改 | |||
| if change_params[:assigned_to_id].present? | |||
| assigner1 = User.find_by_id(change_params[:assigned_to_id][0]) | |||
| assigner2 = User.find_by_id(change_params[:assigned_to_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifassigner}', '<br/>') | |||
| else | |||
| content.sub!('{ifassigner}', '') | |||
| end | |||
| content.sub!('{endassigner}', '') | |||
| content.gsub!('{assigner1}', assigner1.present? ? assigner1&.real_name : '未指派成员') | |||
| content.gsub!('{assigner2}', assigner2.present? ? assigner2&.real_name : '未指派成员') | |||
| else | |||
| content.gsub!(/({ifassigner})(.*)({endassigner})/, '') | |||
| end | |||
| # 合并请求里程碑修改 | |||
| if change_params[:fixed_version_id].present? | |||
| fix_version1 = Version.find_by_id(change_params[:fixed_version_id][0]) | |||
| fix_version2 = Version.find_by_id(change_params[:fixed_version_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifmilestone}', '<br/>') | |||
| else | |||
| content.sub!('{ifmilestone}', '') | |||
| end | |||
| content.sub!('{endmilestone}', '') | |||
| content.gsub!('{milestone1}', fix_version1.present? ? fix_version1&.name : '未选择里程碑') | |||
| content.gsub!('{milestone2}', fix_version2.present? ? fix_version2&.name : '未选择里程碑') | |||
| else | |||
| content.gsub!(/({ifmilestone})(.*)({endmilestone})/, '') | |||
| end | |||
| # 合并请求标记修改 | |||
| if change_params[:issue_tags_value].present? | |||
| issue_tags1 = IssueTag.where(id: change_params[:issue_tags_value][0]).distinct | |||
| issue_tags2 = IssueTag.where(id: change_params[:issue_tags_value][1]).distinct | |||
| tag1 = issue_tags1.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags1.pluck(:name).join(",") | |||
| tag2 = issue_tags2.pluck(:name).join(",").blank? ? '未选择标记' : issue_tags2.pluck(:name).join(",") | |||
| if change_count > 1 | |||
| content.sub!('{iftag}', '<br/>') | |||
| else | |||
| content.sub!('{iftag}', '') | |||
| end | |||
| content.sub!('{endtag}', '') | |||
| content.gsub!('{tag1}', tag1) | |||
| content.gsub!('{tag2}', tag2) | |||
| else | |||
| content.gsub!(/({iftag})(.*)({endtag})()/, '') | |||
| end | |||
| # 合并请求优先级修改 | |||
| if change_params[:priority_id].present? | |||
| priority1 = IssuePriority.find_by_id(change_params[:priority_id][0]) | |||
| priority2 = IssuePriority.find_by_id(change_params[:priority_id][1]) | |||
| if change_count > 1 | |||
| content.sub!('{ifpriority}', '<br/>') | |||
| else | |||
| content.sub!('{ifpriority}', '') | |||
| end | |||
| content.sub!('{ifpriority}', '') | |||
| content.sub!('{endpriority}', '') | |||
| content.gsub!('{priority1}', priority1&.name) | |||
| content.gsub!('{priority2}', priority2&.name) | |||
| else | |||
| content.gsub!(/({ifpriority})(.*)({endpriority})/, '') | |||
| end | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestChanged.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我创建或负责的合并请求被关闭 | |||
| class MessageTemplate::PullRequestClosed < MessageTemplate | |||
| # MessageTemplate::PullRequestClosed.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', pull_request&.title) | |||
| url = notification_url | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestClosed.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # TODO 我创建或负责的合并请求有新的评论 | |||
| class MessageTemplate::PullRequestJournal < MessageTemplate | |||
| # MessageTemplate::PullRequestJournal.get_message_content(User.where(login: 'yystopf')) | |||
| def self.get_message_content(receivers) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestJournal.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -0,0 +1,29 @@ | |||
| # == Schema Information | |||
| # | |||
| # Table name: message_templates | |||
| # | |||
| # id :integer not null, primary key | |||
| # type :string(255) | |||
| # sys_notice :text(65535) | |||
| # email :text(65535) | |||
| # created_at :datetime not null | |||
| # updated_at :datetime not null | |||
| # notification_url :string(255) | |||
| # email_title :string(255) | |||
| # | |||
| # 我创建或负责的合并请求被合并 | |||
| class MessageTemplate::PullRequestMerged < MessageTemplate | |||
| # MessageTemplate::PullRequestMerged.get_message_content(User.where(login: 'yystopf'), User.last, PullRequest.last) | |||
| def self.get_message_content(receivers, operator, pull_request) | |||
| project = pull_request&.project | |||
| owner = project&.owner | |||
| content = sys_notice.gsub('{title}', pull_request&.title) | |||
| url = notification_url.gsub('{owner}', owner&.login).gsub('{identifier}', project&.identifier).gsub('{id}', pull_request&.id.to_s) | |||
| return receivers_string(receivers), content, url | |||
| rescue => e | |||
| Rails.logger.info("MessageTemplate::PullRequestMerged.get_message_content [ERROR] #{e}") | |||
| return '', '', '' | |||
| end | |||
| end | |||
| @@ -18,7 +18,7 @@ class Mirror < ApplicationRecord | |||
| # 0: 同步镜像成功;1: 正在同步镜像;2: 同步失败; 默认值为0 | |||
| enum status: { succeeded: 0, waiting: 1, failed: 2 } | |||
| after_update :websocket_boardcast, if: :saved_change_to_status? | |||
| # after_update :websocket_boardcast, if: :saved_change_to_status? | |||
| belongs_to :repository, foreign_key: :repo_id | |||
| @@ -22,6 +22,9 @@ class OrganizationUser < ApplicationRecord | |||
| validates :user_id, uniqueness: {scope: :organization_id} | |||
| after_create :send_create_message_to_notice_system | |||
| after_destroy :send_destroy_message_to_notice_system | |||
| def self.build(organization_id, user_id) | |||
| org_user = self.find_by(organization_id: organization_id, user_id: user_id) | |||
| return org_user unless org_user.nil? | |||
| @@ -31,4 +34,12 @@ class OrganizationUser < ApplicationRecord | |||
| def teams | |||
| organization.teams.joins(:team_users).where(team_users: {user_id: user_id}) | |||
| end | |||
| def send_create_message_to_notice_system | |||
| SendTemplateMessageJob.perform_later('OrganizationJoined', self.user_id, self.organization_id) | |||
| end | |||
| def send_destroy_message_to_notice_system | |||
| SendTemplateMessageJob.perform_later('OrganizationLeft', self.user_id, self.organization_id) | |||
| end | |||
| end | |||
| @@ -32,9 +32,13 @@ class ProjectUnit < ApplicationRecord | |||
| types.delete("pulls") if project.sync_mirror? | |||
| # 默认code类型自动创建 | |||
| types << "code" | |||
| before_units = project.project_units.pluck(:unit_type).sort | |||
| project.project_units.where.not(unit_type: types).each(&:destroy!) | |||
| types.each do |type| | |||
| project.project_units.find_or_create_by!(unit_type: type) | |||
| end | |||
| after_units = project.project_units.pluck(:unit_type).sort | |||
| return before_units, after_units | |||
| end | |||
| end | |||
| @@ -54,4 +54,15 @@ class Team < ApplicationRecord | |||
| team_users.where(user_id: user_id).present? | |||
| end | |||
| def authorize_name | |||
| case self.authorize | |||
| when 'read' then '报告者' | |||
| when 'write' then '开发者' | |||
| when 'admin' then '管理员' | |||
| when 'owner' then '拥有者' | |||
| else | |||
| '' | |||
| end | |||
| end | |||
| end | |||
| @@ -187,7 +187,7 @@ class User < Owner | |||
| :show_email, :show_location, :show_department, | |||
| :technical_title, :province, :city, :custom_department, to: :user_extension, allow_nil: true | |||
| before_save :update_hashed_password, :set_lastname, :set_profile_completed | |||
| before_save :update_hashed_password, :set_lastname | |||
| after_create do | |||
| SyncTrustieJob.perform_later("user", 1) if allow_sync_to_trustie? | |||
| end | |||
| @@ -770,6 +770,10 @@ class User < Owner | |||
| laboratory_id.present? && laboratory_id != 1 | |||
| end | |||
| def profile_is_completed? | |||
| self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present? | |||
| end | |||
| protected | |||
| def validate_password_length | |||
| # 管理员的初始密码是5位 | |||
| @@ -796,10 +800,6 @@ class User < Owner | |||
| def set_lastname | |||
| self.lastname = self.nickname if changes[:nickname].present? | |||
| end | |||
| def set_profile_completed | |||
| self.profile_completed = self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present? | |||
| end | |||
| end | |||
| @@ -24,6 +24,7 @@ class Watcher < ApplicationRecord | |||
| after_save :reset_cache_data | |||
| after_destroy :reset_cache_data | |||
| after_create :send_create_message_to_notice_system | |||
| def reset_cache_data | |||
| if self.watchable.is_a?(User) | |||
| @@ -35,4 +36,8 @@ class Watcher < ApplicationRecord | |||
| self.reset_platform_cache_async_job | |||
| end | |||
| def send_create_message_to_notice_system | |||
| SendTemplateMessageJob.perform_later('FollowTip', self.id) if self.watchable.is_a?(User) | |||
| end | |||
| end | |||
| @@ -11,7 +11,7 @@ class Projects::ListQuery < ApplicationQuery | |||
| end | |||
| def call | |||
| q = Project.all_visible(current_user_id).by_name_or_identifier(params[:search]) | |||
| q = Project.visible.by_name_or_identifier(params[:search]) | |||
| scope = q | |||
| .with_project_type(params[:project_type]) | |||
| @@ -0,0 +1,108 @@ | |||
| class Notice::Read::ClientService < ApplicationService | |||
| attr_reader :url, :params | |||
| def initialize(options={}) | |||
| @url = options[:url] | |||
| @params = options[:params] | |||
| end | |||
| def post(url, params={}) | |||
| puts "[notice][read][POST] request params: #{params}" | |||
| conn.post do |req| | |||
| req.url = full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def get(url, params={}) | |||
| puts "[notice][read][GET] request params: #{params}" | |||
| conn.get do |req| | |||
| req.url full_url(url, 'get') | |||
| params.each_pair do |key, value| | |||
| req.params["#{key}"] = value | |||
| end | |||
| end | |||
| end | |||
| def delete(url, params={}) | |||
| puts "[notice][read][DELETE] request params: #{params}" | |||
| conn.delete do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def patch(url, params={}) | |||
| puts "[notice][read][PATCH] request params: #{params}" | |||
| conn.patch do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def put(url, params={}) | |||
| puts "[notice][read][PUT] request params: #{params}" | |||
| conn.put do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def platform | |||
| Notice.notice_config[:platform] | |||
| end | |||
| private | |||
| def conn | |||
| @client ||= begin | |||
| Faraday.new(url: domain) do |req| | |||
| req.request :url_encoded | |||
| req.headers['Content-Type'] = 'application/json' | |||
| req.adapter Faraday.default_adapter | |||
| end | |||
| end | |||
| @client | |||
| end | |||
| def base_url | |||
| Notice.notice_config[:base_url] | |||
| end | |||
| def domain | |||
| Notice.notice_config[:read_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 "[notice][read] request url: #{url}" | |||
| return url | |||
| end | |||
| def log_error(status, body) | |||
| puts "[notice][read] status: #{status}" | |||
| puts "[notice][read] body: #{body}" | |||
| end | |||
| def render_response(response) | |||
| status = response.status | |||
| body = JSON.parse(response&.body) | |||
| log_error(status, body) | |||
| if status == 200 | |||
| if body["code"] == 1 | |||
| return [body["code"], body["message"], body["data"]] | |||
| else | |||
| puts "[notice][read][ERROR] code: #{body["code"]}" | |||
| puts "[notice][read][ERROR] message: #{body["message"]}" | |||
| end | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,25 @@ | |||
| class Notice::Read::CountService < Notice::Read::ClientService | |||
| attr_accessor :receiver, :type | |||
| def initialize(receiver, type=-1) | |||
| @receiver = receiver | |||
| @type = type | |||
| end | |||
| def call | |||
| result = get(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_params | |||
| { | |||
| receiver: receiver, | |||
| type: type | |||
| }.stringify_keys | |||
| end | |||
| def url | |||
| "/notification/#{platform}/count".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,32 @@ | |||
| class Notice::Read::ListService < Notice::Read::ClientService | |||
| attr_accessor :receiver, :type, :status, :page, :size | |||
| def initialize(receiver, type=-1, status=2, page=1, size=15) | |||
| @receiver = receiver | |||
| @type = type | |||
| @status = status | |||
| @page = page | |||
| @size = size | |||
| end | |||
| def call | |||
| result = get(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_params | |||
| { | |||
| receiver: receiver, | |||
| page: page, | |||
| status: status, | |||
| size: size, | |||
| type: type | |||
| }.stringify_keys | |||
| end | |||
| def url | |||
| "/notification/#{platform}/list".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,35 @@ | |||
| class Notice::Write::ChangeStatusService < Notice::Write::ClientService | |||
| attr_accessor :notification_ids, :receiver, :type, :status | |||
| def initialize(notification_ids, receiver, type=-1, status=2) | |||
| @notification_ids = notification_ids | |||
| @receiver = receiver | |||
| @type = type | |||
| @status = status | |||
| end | |||
| def call | |||
| result = put(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_notification_ids | |||
| notification_ids.join(",") | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| notificationIds: request_notification_ids, | |||
| receiver: receiver, | |||
| type: type, | |||
| status: status | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/notification/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,108 @@ | |||
| class Notice::Write::ClientService < ApplicationService | |||
| attr_reader :url, :params | |||
| def initialize(options={}) | |||
| @url = options[:url] | |||
| @params = options[:params] | |||
| end | |||
| def post(url, params={}) | |||
| puts "[notice][write][POST] request params: #{params}" | |||
| conn.post do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def get(url, params={}) | |||
| puts "[notice][write][GET] request params: #{params}" | |||
| conn.get do |req| | |||
| req.url full_url(url, 'get') | |||
| params.each_pair do |key, value| | |||
| req.params["#{key}"] = value | |||
| end | |||
| end | |||
| end | |||
| def delete(url, params={}) | |||
| puts "[notice][write][DELETE] request params: #{params}" | |||
| conn.delete do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def patch(url, params={}) | |||
| puts "[notice][write][PATCH] request params: #{params}" | |||
| conn.patch do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def put(url, params={}) | |||
| puts "[notice][write][PUT] request params: #{params}" | |||
| conn.put do |req| | |||
| req.url full_url(url) | |||
| req.body = params[:data].to_json | |||
| end | |||
| end | |||
| def platform | |||
| Notice.notice_config[:platform] | |||
| end | |||
| private | |||
| def conn | |||
| @client ||= begin | |||
| Faraday.new(url: domain) do |req| | |||
| req.request :url_encoded | |||
| req.headers['Content-Type'] = 'application/json' | |||
| req.adapter Faraday.default_adapter | |||
| end | |||
| end | |||
| @client | |||
| end | |||
| def base_url | |||
| Notice.notice_config[:base_url] | |||
| end | |||
| def domain | |||
| Notice.notice_config[:write_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 "[notice][write] request url: #{url}" | |||
| return url | |||
| end | |||
| def log_error(status, body) | |||
| puts "[notice][write] status: #{status}" | |||
| puts "[notice][write] body: #{body}" | |||
| end | |||
| def render_response(response) | |||
| status = response.status | |||
| body = JSON.parse(response&.body) | |||
| log_error(status, body) | |||
| if status == 200 | |||
| if body["code"] == 1 | |||
| return [body["code"], body["message"], body["data"]] | |||
| else | |||
| puts "[notice][write][ERROR] code: #{body["code"]}" | |||
| puts "[notice][write][ERROR] message: #{body["message"]}" | |||
| end | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,42 @@ | |||
| class Notice::Write::CreateService < Notice::Write::ClientService | |||
| attr_accessor :receivers, :sender, :content, :notification_url, :source, :extra, :type | |||
| def initialize(receivers, content, notification_url, source, extra={}, type=1, sender=-1) | |||
| @receivers = receivers | |||
| @sender = sender | |||
| @content = content | |||
| @notification_url = notification_url | |||
| @source = source | |||
| @extra = extra | |||
| @type = type | |||
| end | |||
| def call | |||
| return nil if request_receivers.blank? | |||
| result = post(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_receivers | |||
| receivers.is_a?(Array) ? receivers.join(",") : receivers | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| receivers: request_receivers, | |||
| sender: sender, | |||
| content: content, | |||
| notification_url: notification_url, | |||
| source: source, | |||
| extra: extra.to_json.to_s, | |||
| type: type | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/notification/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,33 @@ | |||
| class Notice::Write::DeleteService < Notice::Write::ClientService | |||
| attr_accessor :notification_ids, :receiver, :type | |||
| def initialize(notification_ids, receiver, type=-1) | |||
| @notification_ids = notification_ids | |||
| @receiver = receiver | |||
| @type = type | |||
| end | |||
| def call | |||
| result = delete(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_notification_ids | |||
| notification_ids.join(",") | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| notificationIds: request_notification_ids, | |||
| receiver: receiver, | |||
| type: type | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/notification/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -0,0 +1,40 @@ | |||
| class Notice::Write::EmailCreateService < Notice::Write::ClientService | |||
| attr_accessor :receivers, :sender, :content, :subject | |||
| def initialize(receivers, subject, content, sender=-1) | |||
| @receivers = receivers | |||
| @sender = sender | |||
| @content = content | |||
| @subject = subject | |||
| end | |||
| def call | |||
| return nil if request_receivers.blank? | |||
| result = post(url, request_params) | |||
| response = render_response(result) | |||
| end | |||
| private | |||
| def request_receivers | |||
| receivers.is_a?(Array) ? receivers.join(",") : receivers | |||
| end | |||
| def request_subject | |||
| "Trustie: #{subject}" | |||
| end | |||
| def request_params | |||
| Hash.new.merge(data: { | |||
| emails: request_receivers, | |||
| sender: sender, | |||
| content: content, | |||
| subject: request_subject | |||
| }.stringify_keys) | |||
| end | |||
| def url | |||
| "/email/#{platform}".freeze | |||
| end | |||
| end | |||
| @@ -53,6 +53,8 @@ class Projects::AcceptJoinService < ApplicationService | |||
| def operate_project_member | |||
| Projects::AddMemberInteractor.call(@project.owner, @project, @applied_project.user, permission) | |||
| SendTemplateMessageJob.perform_later('ProjectJoined', @user.id, @applied_project.user_id, @project.id) | |||
| SendTemplateMessageJob.perform_later('ProjectMemberJoined', @user.id, @applied_project.user_id, @project.id) | |||
| end | |||
| def send_apply_message | |||
| @@ -0,0 +1,65 @@ | |||
| <div class="box search-form-container project-list-form"> | |||
| <div style="line-height: 38px;" class="flex-1"><%= type == "create" ? "新建" : "编辑" %><%= @message_template.simple_type %>消息模版</div> | |||
| <%= link_to "返回", admins_message_templates_path, class: "btn btn-default pull-right" %> | |||
| </div> | |||
| <div class="box"> | |||
| <%= form_for @message_template, url: {controller: "message_templates", action: "#{type}"} do |f| %> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 站内信 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <%= f.text_area :sys_notice, class:"form-control", rows: "10", cols: "20",placeholer: "请输入站内信" %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 站内信跳转地址 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <%= f.text_field :notification_url, class: "form-control input-lg", maxlength: "60", placeholder: "请输入站内信跳转地址" %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 邮件标题 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <%= f.text_field :email_title, class: "form-control input-lg", maxlength: "60", placeholder: "请输入邮件标题" %> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <label> | |||
| <span class="color-grey-6 pt10"> | |||
| 邮件正文 | |||
| <span class="ml10 color-orange mr20">*</span> | |||
| </span> | |||
| </label> | |||
| <div class="mt-10"> | |||
| <div class="pl-0 my-3 setting-item-body" id="message-template-email-editor"> | |||
| <%= f.text_area :email, class:"form-control", style: 'display: none;', rows: "10", cols: "20", placeholer: "请输入邮件正文" %> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="form-group"> | |||
| <%= f.submit "确认", class: "btn btn-primary submit-btn" %> | |||
| </div> | |||
| <% end %> | |||
| </div> | |||
| @@ -0,0 +1,39 @@ | |||
| <table class="table table-hover text-center subject-list-table"> | |||
| <thead class="thead-light"> | |||
| <tr> | |||
| <th width="5%">序号</th> | |||
| <th width="10%">类型</th> | |||
| <th width="35%">系统消息模版</th> | |||
| <th width="30%">邮件模版</th> | |||
| <th width="25%">通知地址</th> | |||
| <th width="10%">操作</th> | |||
| </tr> | |||
| </thead> | |||
| <tbody> | |||
| <% if message_templates.present? %> | |||
| <% message_templates.each_with_index do |message_template_type, index| %> | |||
| <% message_template = message_template_type.constantize.last%> | |||
| <tr class="project-language-item-<%= message_template.id %>"> | |||
| <td><%= list_index_no((params[:page] || 1).to_i, index) %></td> | |||
| <td><%= message_template.simple_type %></td> | |||
| <td> | |||
| <%= message_template.sys_notice.to_s.truncate(200) %> | |||
| </td> | |||
| <td> | |||
| <%= message_template.email.to_s.truncate(100) %> | |||
| </td> | |||
| <td> | |||
| <%= message_template.notification_url.to_s.truncate(200) %> | |||
| </td> | |||
| <td class="action-container"> | |||
| <%= link_to "编辑", edit_admins_message_template_path(message_template),remote: true, class: "action" %> | |||
| </td> | |||
| </tr> | |||
| <% end %> | |||
| <% else %> | |||
| <%= render 'admins/shared/no_data_for_table' %> | |||
| <% end %> | |||
| </tbody> | |||
| </table> | |||
| <%= render partial: 'admins/shared/paginate', locals: { objects: message_templates } %> | |||
| @@ -0,0 +1,2 @@ | |||
| $("#admins-message-templates-content").html("<%= j render partial: 'admins/message_templates/form', locals:{type: 'update'} %>") | |||
| createMDEditor('message-template-email-editor', { height: 500, placeholder: '请输入邮件模版' }); | |||
| @@ -0,0 +1,12 @@ | |||
| <% define_admin_breadcrumbs do %> | |||
| <% add_admin_breadcrumb('消息模版') %> | |||
| <% end %> | |||
| <div id="admins-message-templates-content"> | |||
| <div class="box search-form-container project-list-form"> | |||
| <%= link_to "初始化数据", init_data_admins_message_templates_path, class: "btn btn-primary pull-right", "data-disabled-with":"...初始化数据" %> | |||
| </div> | |||
| <div class="box admin-list-container message-templates-list-container"> | |||
| <%= render partial: 'admins/message_templates/list', locals: { message_templates: @message_templates } %> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1 @@ | |||
| $('.message-templates-list-container').html("<%= j( render partial: 'admins/message_templates/list', locals: { message_templates: @message_templates } ) %>"); | |||
| @@ -30,6 +30,7 @@ | |||
| </li> | |||
| <li><%= sidebar_item(admins_reversed_keywords_path, '系统保留关键词', icon: 'key', controller: 'admins-reversed_keywords') %></li> | |||
| <li><%= sidebar_item(admins_message_templates_path, '消息模版', icon: 'folder', controller: 'admins-message_templates') %></li> | |||
| <li><%= sidebar_item(admins_laboratories_path, '云上实验室', icon: 'cloud', controller: 'admins-laboratories') %></li> | |||
| @@ -12,8 +12,8 @@ json.tidding_count 0 | |||
| json.user_phone_binded @user.phone.present? | |||
| json.need_edit_info @user.need_edit_info? | |||
| # json.phone @user.phone | |||
| json.email @user.mail | |||
| json.profile_completed @user.profile_completed? | |||
| # json.email @user.mail | |||
| json.profile_completed @user.profile_is_completed? | |||
| json.professional_certification @user.professional_certification | |||
| json.devops_step @user.devops_step | |||
| json.ci_certification @user.ci_certification? | |||
| @@ -22,4 +22,5 @@ json.province @user.province | |||
| json.city @user.city | |||
| json.custom_department @user.custom_department | |||
| json.description @user.description | |||
| json.(@user, :show_email, :show_department, :show_location) | |||
| json.(@user, :show_email, :show_department, :show_location) | |||
| json.message_unread_total @message_unread_total | |||
| @@ -0,0 +1,24 @@ | |||
| json.id message["id"] | |||
| # json.receiver do | |||
| # json.partial! '/users/user_simple', locals: {user: current_user} | |||
| # end | |||
| json.status message["status"] | |||
| json.content message["content"] | |||
| json.notification_url message["notification_url"] | |||
| json.source message["source"] | |||
| json.time_ago time_from_now(message["created_at"].to_time) | |||
| case message["type"] | |||
| when 1 | |||
| json.type "notification" | |||
| when 2 | |||
| json.type "atme" | |||
| json.sender do | |||
| sender = User.find_by_id(message["sender"]) | |||
| if sender.present? | |||
| json.partial! '/users/user_simple', locals: {user: sender} | |||
| else | |||
| json.nil | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,7 @@ | |||
| json.total_count @data["records_count"] | |||
| json.type %w(notification atme).include?(params[:type]) ? params[:type] : "" | |||
| json.unread_notification @data["unread_notification"] | |||
| json.unread_atme @data["unread_atme"] | |||
| json.messages @data["records"].each do |message| | |||
| json.partial! "message", message: message.stringify_keys | |||
| end | |||
| @@ -62,6 +62,11 @@ default: &default | |||
| domain: 'https://testgit.trustie.net' | |||
| base_url: '/api/v1' | |||
| notice: | |||
| platform: '' | |||
| write_domain: '' | |||
| read_domain: '' | |||
| base_url: '' | |||
| production: | |||
| <<: *default | |||
| @@ -18,7 +18,7 @@ default: &default | |||
| password: 123456 | |||
| # socket: /var/run/mysqld/mysqld.sock | |||
| gitea_server: | |||
| aadapter: mysql2 | |||
| adapter: mysql2 | |||
| database: gitea_development | |||
| host: 127.0.0.1 | |||
| username: root | |||
| @@ -31,7 +31,7 @@ zh-CN: | |||
| branch_name: 分支 | |||
| close_pr: 合并 | |||
| merge: 合并 | |||
| issue_tags_value: 标签 | |||
| issue_tags_value: 标记 | |||
| lock_issue: 锁定工单 | |||
| unlock_issue: 解锁工单 | |||
| destroy_issue_depend: 删除依赖 | |||
| @@ -55,7 +55,7 @@ zh-CN: | |||
| f: 否 | |||
| true: 是 | |||
| false: 否 | |||
| issue_tag_ids: 标签 | |||
| issue_tag_ids: 标记 | |||
| issue_type: 分类 | |||
| token: 悬赏金额 | |||
| close_issue: 工单 | |||
| @@ -300,6 +300,15 @@ Rails.application.routes.draw do | |||
| # resources :recent_contacts, only: [:index] | |||
| # resource :private_message_details, only: [:show] | |||
| # resource :unread_message_info, only: [:show] | |||
| # 通知中心 | |||
| resources :messages, only: [:index, :create] do | |||
| collection do | |||
| post :read | |||
| end | |||
| end | |||
| delete 'messages', to: 'messages#delete' | |||
| end | |||
| resources :tidings, only: [:index] | |||
| @@ -659,6 +668,11 @@ Rails.application.routes.draw do | |||
| resources :project_licenses | |||
| resources :project_ignores | |||
| resources :reversed_keywords | |||
| resources :message_templates, only: [:index, :edit, :update] do | |||
| collection do | |||
| get :init_data | |||
| end | |||
| end | |||
| resources :major_informations, only: [:index] | |||
| resources :ec_templates, only: [:index, :destroy] do | |||
| collection do | |||
| @@ -8,3 +8,4 @@ | |||
| - [notify, 100] | |||
| - [mailers, 101] | |||
| - [cache, 10] | |||
| - [message, 20] | |||
| @@ -2,3 +2,8 @@ sync_gitea_repo_update_time: | |||
| cron: "0 0 * * *" | |||
| class: "SyncRepoUpdateTimeJob" | |||
| queue: default | |||
| delay_expired_issue: | |||
| cron: "0 0 * * *" | |||
| class: "DelayExpiredIssueJob" | |||
| queue: message | |||
| @@ -0,0 +1,11 @@ | |||
| class CreateMessageTemplates < ActiveRecord::Migration[5.2] | |||
| def change | |||
| create_table :message_templates do |t| | |||
| t.string :type | |||
| t.text :sys_notice | |||
| t.text :email | |||
| t.timestamps | |||
| end | |||
| end | |||
| end | |||
| @@ -0,0 +1,5 @@ | |||
| class AddNotificationUrlToMessageTemplates < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :message_templates, :notification_url, :string | |||
| end | |||
| end | |||
| @@ -0,0 +1,5 @@ | |||
| class AddEmailTitleToMessageTemplates < ActiveRecord::Migration[5.2] | |||
| def change | |||
| add_column :message_templates, :email_title, :string | |||
| end | |||
| end | |||
| @@ -345,6 +345,18 @@ | |||
| <li> | |||
| <a href="#1ae74893b1" class="toc-h2 toc-link" data-title="获取当前登陆用户信息">获取当前登陆用户信息</a> | |||
| </li> | |||
| <li> | |||
| <a href="#5b752913ae" class="toc-h2 toc-link" data-title="用户消息列表">用户消息列表</a> | |||
| </li> | |||
| <li> | |||
| <a href="#94306b2fc3" class="toc-h2 toc-link" data-title="发送消息">发送消息</a> | |||
| </li> | |||
| <li> | |||
| <a href="#d69a1523bb" class="toc-h2 toc-link" data-title="阅读消息">阅读消息</a> | |||
| </li> | |||
| <li> | |||
| <a href="#c5dc622a5a" class="toc-h2 toc-link" data-title="删除消息">删除消息</a> | |||
| </li> | |||
| <li> | |||
| <a href="#c6da6881ac" class="toc-h2 toc-link" data-title="更改用户信息">更改用户信息</a> | |||
| </li> | |||
| @@ -909,7 +921,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <!-- | |||
| * @Date: 2021-03-01 10:35:21 | |||
| * @LastEditors: viletyy | |||
| * @LastEditTime: 2021-06-11 16:28:51 | |||
| * @LastEditTime: 2021-09-15 18:00:10 | |||
| * @FilePath: /forgeplus/app/docs/slate/source/includes/_users.md | |||
| --> | |||
| <h1 id='users'>Users</h1><h2 id='1ae74893b1'>获取当前登陆用户信息</h2> | |||
| @@ -971,6 +983,468 @@ Success — a happy kitten is an authenticated kitten! | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| <h2 id='5b752913ae'>用户消息列表</h2> | |||
| <p>获取用户消息列表</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/:login/messages.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/messages.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-2'>HTTP 请求</h3> | |||
| <p><code>GET api/users/yystopf/messages.json</code></p> | |||
| <h3 id='aa883f5d52'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>type</td> | |||
| <td>string</td> | |||
| <td>消息类型,不传为所有消息,notification为系统消息,atme为@我消息</td> | |||
| </tr> | |||
| <tr> | |||
| <td>status</td> | |||
| <td>integer</td> | |||
| <td>是否已读,不传为所有消息,1为未读,2为已读</td> | |||
| </tr> | |||
| <tr> | |||
| <td>limit</td> | |||
| <td>integer</td> | |||
| <td>每页个数</td> | |||
| </tr> | |||
| <tr> | |||
| <td>page</td> | |||
| <td>integer</td> | |||
| <td>页码</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-2'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>total_count</td> | |||
| <td>integer</td> | |||
| <td>消息总数</td> | |||
| </tr> | |||
| <tr> | |||
| <td>type</td> | |||
| <td>string</td> | |||
| <td>消息类型</td> | |||
| </tr> | |||
| <tr> | |||
| <td>unread_notification</td> | |||
| <td>integer</td> | |||
| <td>未读系统通知数量</td> | |||
| </tr> | |||
| <tr> | |||
| <td>unread_atme</td> | |||
| <td>integer</td> | |||
| <td>未读@我数量</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.id</td> | |||
| <td>integer</td> | |||
| <td>消息id</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.status</td> | |||
| <td>integer</td> | |||
| <td>消息是否已读,1为未读,2为已读</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.content</td> | |||
| <td>string</td> | |||
| <td>消息内容</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.notification_url</td> | |||
| <td>string</td> | |||
| <td>消息跳转地址</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.source</td> | |||
| <td>string</td> | |||
| <td>消息来源</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.timeago</td> | |||
| <td>string</td> | |||
| <td>消息时间</td> | |||
| </tr> | |||
| <tr> | |||
| <td>messages.type</td> | |||
| <td>string</td> | |||
| <td>消息类型,notification为系统消息,atme为@我消息</td> | |||
| </tr> | |||
| <tr> | |||
| <td>sender</td> | |||
| <td>object</td> | |||
| <td>消息发送者</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h4 id='source'>消息来源source字段说明</h4> | |||
| <table><thead> | |||
| <tr> | |||
| <th>类型</th> | |||
| <th>说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>IssueAssigned</td> | |||
| <td>有新指派给我的易修</td> | |||
| </tr> | |||
| <tr> | |||
| <td>IssueAssignerExpire</td> | |||
| <td>我负责的易修截止日期到达最后一天</td> | |||
| </tr> | |||
| <tr> | |||
| <td>IssueAtme</td> | |||
| <td>在易修中@我</td> | |||
| </tr> | |||
| <tr> | |||
| <td>IssueChanged</td> | |||
| <td>我创建或负责的易修状态变更</td> | |||
| </tr> | |||
| <tr> | |||
| <td>IssueCreatorExpire</td> | |||
| <td>我创建的易修截止日期到达最后一天</td> | |||
| </tr> | |||
| <tr> | |||
| <td>IssueDeleted</td> | |||
| <td>我创建或负责的易修删除</td> | |||
| </tr> | |||
| <tr> | |||
| <td>IssueJournal</td> | |||
| <td>我创建或负责的易修有新的评论</td> | |||
| </tr> | |||
| <tr> | |||
| <td>LoginIpTip</td> | |||
| <td>登录异常提示</td> | |||
| </tr> | |||
| <tr> | |||
| <td>OrganizationJoined</td> | |||
| <td>账号被拉入组织</td> | |||
| </tr> | |||
| <tr> | |||
| <td>OrganizationLeft</td> | |||
| <td>账号被移出组织</td> | |||
| </tr> | |||
| <tr> | |||
| <td>OrganizationRole</td> | |||
| <td>账号组织权限变更</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectDeleted</td> | |||
| <td>我关注的仓库被删除</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectFollowed</td> | |||
| <td>我管理的仓库被关注</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectForked</td> | |||
| <td>我管理的仓库被复刻</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectIssue</td> | |||
| <td>我管理/关注的仓库有新的易修</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectJoined</td> | |||
| <td>账号被拉入项目</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectLeft</td> | |||
| <td>账号被移出项目</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectMemberJoined</td> | |||
| <td>我管理的仓库有成员加入</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectMemberLeft</td> | |||
| <td>我管理的仓库有成员移出</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectMilestone</td> | |||
| <td>我管理的仓库有新的里程碑</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectPraised</td> | |||
| <td>我管理的仓库被点赞</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectPullRequest</td> | |||
| <td>我管理/关注的仓库有新的合并请求</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectRole</td> | |||
| <td>账号仓库权限变更</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectSettingChanged</td> | |||
| <td>我管理的仓库项目设置被更改</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectTransfer</td> | |||
| <td>我关注的仓库被转移</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ProjectVersion</td> | |||
| <td>我关注的仓库有新的发行版</td> | |||
| </tr> | |||
| <tr> | |||
| <td>PullRequestAssigned</td> | |||
| <td>有新指派给我的合并请求</td> | |||
| </tr> | |||
| <tr> | |||
| <td>PullReuqestAtme</td> | |||
| <td>在合并请求中@我</td> | |||
| </tr> | |||
| <tr> | |||
| <td>PullRequestChanged</td> | |||
| <td>我创建或负责的合并请求状态变更</td> | |||
| </tr> | |||
| <tr> | |||
| <td>PullRequestClosed</td> | |||
| <td>我创建或负责的合并请求被关闭</td> | |||
| </tr> | |||
| <tr> | |||
| <td>PullRequestJournal</td> | |||
| <td>我创建或负责的合并请求有新的评论</td> | |||
| </tr> | |||
| <tr> | |||
| <td>PullRequestMerged</td> | |||
| <td>我创建或负责的合并请求被合并</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"total_count"</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"unread_notification"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"unread_atme"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"messages"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> | |||
| </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Atme Message Content 1"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"notification_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://www.baidu.com"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"PullRequestAtme"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1天前"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"atme"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"sender"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge2"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge2"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/236_177_85/120.png"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span><span class="p">},</span><span class="w"> | |||
| </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Atme Message Content 2"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"notification_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://www.baidu.com"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"IssueAtme"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1天前"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"atme"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"sender"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"User"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"login"</span><span class="p">:</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"image_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"system/lets/letter_avatars/2/T/19_237_174/120.png"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span><span class="p">},</span><span class="w"> | |||
| </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Notification Message Content 1"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"notification_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://www.baidu.com"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"IssueDelete"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1天前"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"notification"</span><span class="w"> | |||
| </span><span class="p">},</span><span class="w"> | |||
| </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Notification Message Content 2"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"notification_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://www.baidu.com"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"IssueChanged"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1天前"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"notification"</span><span class="w"> | |||
| </span><span class="p">},</span><span class="w"> | |||
| </span><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"content"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Notification Message Content 3"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"notification_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://www.baidu.com"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"source"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ProjectJoined"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"time_ago"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1天前"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"notification"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span><span class="p">]</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div> | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| <h2 id='94306b2fc3'>发送消息</h2> | |||
| <p>发送消息, 目前只支持atme</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/:login/messages.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/users/:login/messages.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-3'>HTTP 请求</h3> | |||
| <p><code>POST api/users/yystopf/messages.json</code></p> | |||
| <h3 id='aa883f5d52-2'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>type</td> | |||
| <td>string</td> | |||
| <td>消息类型</td> | |||
| </tr> | |||
| <tr> | |||
| <td>receivers_login</td> | |||
| <td>array</td> | |||
| <td>需要发送消息的用户名数组</td> | |||
| </tr> | |||
| <tr> | |||
| <td>atmeable_type</td> | |||
| <td>string</td> | |||
| <td>atme消息对象,是从哪里@我的,比如评论:Journal、易修:Issue、合并请求:PullRequest</td> | |||
| </tr> | |||
| <tr> | |||
| <td>atmeable_id</td> | |||
| <td>integer</td> | |||
| <td>atme消息对象id</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <blockquote> | |||
| <p>请求的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"atme"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"receivers_login"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"yystopf"</span><span class="p">,</span><span class="w"> </span><span class="s2">"testforge1"</span><span class="p">],</span><span class="w"> | |||
| </span><span class="nl">"atmeable_type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Journal"</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"atmeable_id"</span><span class="p">:</span><span class="w"> </span><span class="mi">67</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div> | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| <h2 id='d69a1523bb'>阅读消息</h2> | |||
| <p>阅读消息</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/:login/messages/read.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">POST /api/users/:login/messages/read.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-4'>HTTP 请求</h3> | |||
| <p><code>POST api/users/yystopf/messages/read.json</code></p> | |||
| <h3 id='aa883f5d52-3'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>type</td> | |||
| <td>string</td> | |||
| <td>消息类型,不传为所有消息,notification为系统消息,atme为@我消息</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ids</td> | |||
| <td>array</td> | |||
| <td>消息id数组,包含-1则把所有未读消息标记为已读</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div> | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| <h2 id='c5dc622a5a'>删除消息</h2> | |||
| <p>删除消息</p> | |||
| <blockquote> | |||
| <p>示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> DELETE http://localhost:3000/api/users/:login/messages.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">DELETE /api/users/:login/messages.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-5'>HTTP 请求</h3> | |||
| <p><code>DELETE api/users/yystopf/messages.json</code></p> | |||
| <h3 id='aa883f5d52-4'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| <th>类型</th> | |||
| <th>字段说明</th> | |||
| </tr> | |||
| </thead><tbody> | |||
| <tr> | |||
| <td>type</td> | |||
| <td>string</td> | |||
| <td>消息类型,atme为@我消息</td> | |||
| </tr> | |||
| <tr> | |||
| <td>ids</td> | |||
| <td>array</td> | |||
| <td>消息id数组,包含-1则把所有消息删除</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <blockquote> | |||
| <p>返回的JSON示例:</p> | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight json tab-json"><code><span class="p">{</span><span class="w"> | |||
| </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> | |||
| </span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"success"</span><span class="w"> | |||
| </span><span class="p">}</span><span class="w"> | |||
| </span></code></pre></div> | |||
| <aside class="success"> | |||
| Success Data. | |||
| </aside> | |||
| <h2 id='c6da6881ac'>更改用户信息</h2> | |||
| <p>更改用户信息</p> | |||
| @@ -979,9 +1453,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> PATCH/PUT http://localhost:3000/api/users/yystopf.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">PATCH/PUT /api/users/:login.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-2'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-6'>HTTP 请求</h3> | |||
| <p><code>PATCH/PUT /api/users/:login.json</code></p> | |||
| <h3 id='aa883f5d52'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-5'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1077,9 +1551,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/is_pinned_projects.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/is_pinned_projects.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-3'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-7'>HTTP 请求</h3> | |||
| <p><code>GET api/users/:login/is_pinned_projects.json</code></p> | |||
| <h3 id='7447e4874e-2'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-3'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1264,9 +1738,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/is_pinned_projects/pin.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/is_pinned_projects/pin.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-4'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-8'>HTTP 请求</h3> | |||
| <p><code>POST /api/users/:login/is_pinned_projects/pin.json</code></p> | |||
| <h3 id='aa883f5d52-2'>请求字段说明:</h3><h4 id='0ca7f0efb8'>同时设定多个星标项目</h4> | |||
| <h3 id='aa883f5d52-6'>请求字段说明:</h3><h4 id='0ca7f0efb8'>同时设定多个星标项目</h4> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1310,9 +1784,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> PATCH http://localhost:3000/api/users/yystopf/is_pinned_projects/11.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">PATCH/PUT /api/users/:login/is_pinned_projects/:id.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-5'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-9'>HTTP 请求</h3> | |||
| <p><code>PATCH/PUT /api/users/:login/is_pinned_projects/:id.json</code></p> | |||
| <h3 id='aa883f5d52-3'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-7'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1351,9 +1825,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/statistics/activity.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/statistics/activity.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-6'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-10'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/statistics/activity.json</code></p> | |||
| <h3 id='7447e4874e-3'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-4'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1440,9 +1914,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/headmaps.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/headmaps.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-7'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-11'>HTTP 请求</h3> | |||
| <p><code>GET api/users/:login/headmaps.json</code></p> | |||
| <h3 id='aa883f5d52-4'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-8'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1456,7 +1930,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>年份</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-4'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-5'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1585,9 +2059,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/project_trends.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/project_trends.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-8'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-12'>HTTP 请求</h3> | |||
| <p><code>GET api/users/:login/project_trends.json</code></p> | |||
| <h3 id='aa883f5d52-5'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-9'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1601,7 +2075,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>日期,格式: 2021-05-28</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-5'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-6'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1902,9 +2376,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/statistics/develop.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/statistics/develop.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-9'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-13'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/statistics/develop.json</code></p> | |||
| <h3 id='aa883f5d52-6'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-10'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -1923,7 +2397,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>时间戳,结束时间,格式:1622131200</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-6'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-7'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2045,9 +2519,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/statistics/role.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/statistics/role.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-10'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-14'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/statistics/role.json</code></p> | |||
| <h3 id='aa883f5d52-7'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-11'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2066,7 +2540,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>时间戳,结束时间,格式:1622131200</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-7'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-8'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2127,9 +2601,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/statistics/major.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/statistics/major.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-11'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-15'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/statistics/major.json</code></p> | |||
| <h3 id='aa883f5d52-8'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-12'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2148,7 +2622,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>时间戳,结束时间,格式:1622131200</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-8'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-9'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2188,9 +2662,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/applied_messages.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_messages.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-12'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-16'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_messages.json</code></p> | |||
| <h3 id='aa883f5d52-9'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-13'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2204,7 +2678,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>用户标识</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-9'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-10'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2467,9 +2941,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/applied_transfer_projects.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_transfer_projects.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-13'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-17'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_transfer_projects.json</code></p> | |||
| <h3 id='aa883f5d52-10'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-14'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2483,7 +2957,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>用户标识</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-10'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-11'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2659,9 +3133,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/accept.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_transfer_projects/:id/accept.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-14'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-18'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_transfer_projects/:id/accept.json</code></p> | |||
| <h3 id='aa883f5d52-11'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-15'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2680,7 +3154,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>迁移id</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-11'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-12'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2850,9 +3324,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/applied_transfer_projects/2/refuse.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_transfer_projects/:id/refuse.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-15'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-19'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_transfer_projects/:id/refuse.json</code></p> | |||
| <h3 id='aa883f5d52-12'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-16'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -2871,7 +3345,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>迁移id</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-12'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-13'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -3041,9 +3515,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> GET http://localhost:3000/api/users/yystopf/applied_projects.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_projects.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-16'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-20'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_projects.json</code></p> | |||
| <h3 id='aa883f5d52-13'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-17'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -3057,7 +3531,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>用户标识</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-13'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-14'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -3201,9 +3675,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/applied_projects/2/accept.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_projects/:id/accept.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-17'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-21'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_projects/:id/accept.json</code></p> | |||
| <h3 id='aa883f5d52-14'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-18'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -3222,7 +3696,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>申请id</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-14'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-15'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -3360,9 +3834,9 @@ Success — a happy kitten is an authenticated kitten! | |||
| </blockquote> | |||
| <div class="highlight"><pre class="highlight shell tab-shell"><code>curl <span class="nt">-X</span> POST http://localhost:3000/api/users/yystopf/applied_projects/2/refuse.json | |||
| </code></pre></div><div class="highlight"><pre class="highlight javascript tab-javascript"><code><span class="k">await</span> <span class="nx">octokit</span><span class="p">.</span><span class="nx">request</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET /api/users/:login/applied_projects/:id/refuse.json</span><span class="dl">'</span><span class="p">)</span> | |||
| </code></pre></div><h3 id='http-18'>HTTP 请求</h3> | |||
| </code></pre></div><h3 id='http-22'>HTTP 请求</h3> | |||
| <p><code>GET /api/users/:login/applied_projects/:id/refuse.json</code></p> | |||
| <h3 id='aa883f5d52-15'>请求字段说明:</h3> | |||
| <h3 id='aa883f5d52-19'>请求字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -3381,7 +3855,7 @@ Success — a happy kitten is an authenticated kitten! | |||
| <td>申请id</td> | |||
| </tr> | |||
| </tbody></table> | |||
| <h3 id='7447e4874e-15'>返回字段说明:</h3> | |||
| <h3 id='7447e4874e-16'>返回字段说明:</h3> | |||
| <table><thead> | |||
| <tr> | |||
| <th>参数</th> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>有新的易修指派给我</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 指派给你一个易修:<a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a><br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>加入组织</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| 你已加入 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{organization}</a> 组织<br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>移出组织</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| 你已被移出 <a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{organization}</a> 组织<br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>管理的仓库有新的易修</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 新建了一个易修:<a href="{baseurl}/{login2}/{identifier}/issues/{id}" style="font-weight:bold;color:#3b94d6;">{title}</a><br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>加入项目</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| 你已加入 <a href="{baseurl}/{login}/{identifier}" style="font-weight:bold;color:#3b94d6;">{nickname}/{repository}</a> 项目<br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>移出项目</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| 你已被移出 <a href="{baseurl}/{login}/{identifier}" style="font-weight:bold;color:#3b94d6;">{nickname}/{repository}</a> 项目<br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>管理的仓库有成员变更</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a> 已加入项目 <a href="{baseurl}/{login2}/{identifier}" style="font-weight:bold;color:#3b94d6;">{nickname2}/{repository}</a><br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>管理的仓库有成员变更</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a> 已被移出项目 <a href="{baseurl}/{login2}/{identifier}" style="font-weight:bold;color:#3b94d6;">{nickname2}/{repository}</a><br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>管理的仓库有新的合并请求</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 提交了一个合并请求:<a href="{baseurl}/{login2}/{identifier}/pulls/{id}/Messagecount" style="font-weight:bold;color:#3b94d6;">{title}</a><br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,58 @@ | |||
| <html> | |||
| <head> | |||
| <title>管理的仓库设置被更改</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a> 更改 <a href="{baseurl}/{login2}/{identifier}/settings" style="font-weight:bold;color:#3b94d6;">{nickname2}/{repository} 的仓库设置:</a> | |||
| {ifname}更改项目名称为"{name}"{endname} | |||
| {ifdescription}更改项目简介为"{description}"{enddescription} | |||
| {ifcategory}更改项目类别为"{category}"{endcategory} | |||
| {iflanguage}更改项目语言为"{language}"{endlanguage} | |||
| {ifpermission}将仓库设为"{permission}"{endpermission} | |||
| {ifnavbar}将项目导航更改为"{navbar}"{endnavbar} | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,52 @@ | |||
| <html> | |||
| <head> | |||
| <title>有新的合并请求指派给我</title> | |||
| <style type="text/css"> | |||
| body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;} | |||
| body,table,input,textarea,select,button { font-family: "微软雅黑","宋体"; font-size:12px;line-height:1.5; background:#eaebec;} | |||
| div,img,tr,td,table{ border:0;} | |||
| table,tr,td{border:0;} | |||
| ol,ul,li{ list-style-type:none} | |||
| .new_content{ background:#fff; width: 100%;} | |||
| .email-page-link{ } | |||
| .email-link-top{ } | |||
| .c_white{ color:#fff;} | |||
| .email-link-con{ } | |||
| .email-link-line{ } | |||
| .email-link-footer{ padding:15px; color:#333; line-height: 1.9; } | |||
| .c_grey02{ color: #888;} | |||
| .fb{ font-weight: normal;} | |||
| .f14{ } | |||
| </style> | |||
| </head> | |||
| <body style="background:#fff;"> | |||
| <div class="new_content"> | |||
| <div style="width: 598px; background:#fff; margin:20px auto;"> | |||
| <div style="height:50px; width: 578px; background:#3b94d6; padding:9px 10px 6px;border:1px solid #ddd; border-bottom:none;"> | |||
| <a href="https://www.trustie.net/"><img src="http://www.trustie.net/images/nav_logo.png" width="51" height="45" ></a> | |||
| <p style="color:#fff; float:right; margin-top:15px;">确实让创新更美好</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| <div style="width: 558px; border-left:1px solid #ddd;border-right:1px solid #ddd; background:#fff; padding:20px; color:#333; line-height: 1.9;"> | |||
| <p style="font-size: 14px; color:#333;"> | |||
| {receiver},您好!<br/> | |||
| <a href="{baseurl}/{login1}" style="font-weight:bold;color:#3b94d6;">{nickname1}</a>在 {nickname2}/{repository} 指派给你一个合并请求:<a href="{baseurl}/{login2}/{identifier}/pulls/{id}/Messagecount" style="font-weight:bold;color:#3b94d6;">{title}</a><br/> | |||
| </p> | |||
| <div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div> | |||
| <img src="https://www.trustie.net/images/wechat/trustie_QR.jpg" width="120" height="120" > | |||
| <p style=" color:#666;"> | |||
| 扫一扫,关注trustie微信公众号,更方便获取平台动态,消息推送等提醒<br/> | |||
| 想了解更多信息,请访问 <a href="https://www.trustie.net/" style=" color:#3b94d6;"> www.trustie.net</a> | |||
| </p> | |||
| </div> | |||
| <div style="padding:20px; color:#333; line-height: 1.9;background: #eee;border:1px solid #ddd; border-top:none; width: 558px;"> | |||
| <p style="color:#888; float:left;">如果您在使用中有任何的疑问和建议,欢迎您给我们反馈意见<br/> | |||
| QQ群:1071514693</p> | |||
| <p style="color:#888; float:right;font-weight: bold;font-size: 16px;">Trustie团队</p> | |||
| <div style="clear:both; overflow:hidden;"></div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,5 @@ | |||
| require 'rails_helper' | |||
| RSpec.describe MessageTemplate, type: :model do | |||
| pending "add some examples to (or delete) #{__FILE__}" | |||
| end | |||