Merge branch 'develop' into standalone_develop

This commit is contained in:
yystopf 2021-12-28 16:10:16 +08:00
commit 96b0f2d167
24 changed files with 393 additions and 52 deletions

View File

@ -7,6 +7,7 @@ class AccountsController < ApplicationController
# 其他平台同步注册的用户
def remote_register
Register::RemoteForm.new(remote_register_params).validate!
username = params[:username]&.gsub(/\s+/, "")
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
email = params[:email]&.gsub(/\s+/, "")
@ -375,5 +376,9 @@ class AccountsController < ApplicationController
phone_or_mail = strip(reset_password_params[:login])
User.where("phone = :search OR mail = :search", search: phone_or_mail).last
end
def remote_register_params
params.permit(:username, :email, :password, :platform)
end
end

View File

@ -42,12 +42,14 @@ class CompareController < ApplicationController
end
def load_compare_params
@base = Addressable::URI.unescape(params[:base])
# @base = Addressable::URI.unescape(params[:base])
@base = Base64.decode64(params[:base])
@head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head]
# @head = Addressable::URI.unescape(@head)
@head = Base64.decode64(@head)
end
def gitea_compare(base, head)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, CGI.escape(base), CGI.escape(head), current_user.gitea_token)
end
end

View File

@ -486,7 +486,8 @@ class IssuesController < ApplicationController
end
def operate_issue_permission
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
@issue = Issue.find_by_id(params[:id]) unless @issue.present?
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id))
end
def export_issues(issues)

View File

@ -28,7 +28,7 @@ class Organizations::OrganizationsController < Organizations::BaseController
def create
ActiveRecord::Base.transaction do
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate!
Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate!
@organization = Organizations::CreateService.call(current_user, organization_params)
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
end

View File

@ -18,7 +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) if Site.has_notice_menu?
SendTemplateMessageJob.perform_later('TeamJoined', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
end
rescue Exception => e
@ -31,6 +31,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
ActiveRecord::Base.transaction do
@team_user.destroy!
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
SendTemplateMessageJob.perform_later('TeamLeft', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
org_team_users = @organization.team_users.where(user_id: @operate_user.id)
unless org_team_users.present?
@organization.organization_users.find_by(user_id: @operate_user.id).destroy!

View File

@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
before_action :check_project_public
def index
project_trends = @project.project_trends.preload(:user, trend: :user)
project_trends = @project.project_trends.preload(:user, trend: :user, project: :owner)
check_time = params[:time] #时间的筛选
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version

View File

@ -238,7 +238,7 @@ class RepositoriesController < ApplicationController
def archive
domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{URI.escape(params[:archive])}"
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{CGI.escape(params[:archive])}"
file_path = [domain, api_url, archive_url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
@ -252,11 +252,11 @@ class RepositoriesController < ApplicationController
domain = Gitea.gitea_config[:domain]
api_url = Gitea.gitea_config[:base_url]
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}"
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{URI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
file_path = [domain, api_url, url].join
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&")
redirect_to URI.escape(file_path)
redirect_to file_path
end
private

View File

@ -0,0 +1,16 @@
module Register
class RemoteForm < Register::BaseForm
# login 登陆方式,支持邮箱、登陆、手机号等
attr_accessor :username, :email, :password, :platform
validates :username, :email, :password, presence: true
validate :check!
def check!
Rails.logger.info "Register::RemoteForm params: username: #{username}; email: #{email}; password: #{password}; platform: #{platform}"
check_login(username)
check_mail(email)
check_password(password)
end
end
end

View File

@ -94,18 +94,6 @@ class SendTemplateMessageJob < ApplicationJob
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)
@ -276,6 +264,32 @@ class SendTemplateMessageJob < ApplicationJob
receivers_email_string, email_title, email_content = MessageTemplate::PullRequestMerged.get_email_message_content(receiver, operator, pull_request)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'TeamJoined'
user_id, organization_id, team_id = args[0], args[1], args[2]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
team = Team.find_by_id(team_id)
return unless user.present? && organization.present? && team.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::TeamJoined.get_message_content(receivers, organization, team)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::TeamJoined.get_email_message_content(receiver, organization, team)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
when 'TeamLeft'
user_id, organization_id, team_id = args[0], args[1], args[2]
user = User.find_by_id(user_id)
organization = Organization.find_by_id(organization_id)
team = Team.find_by_id(team_id)
return unless user.present? && organization.present? && team.present?
receivers = User.where(id: user.id)
receivers_string, content, notification_url = MessageTemplate::TeamLeft.get_message_content(receivers, organization, team)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user.id, organization_id: organization.id, team_id: team.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::TeamLeft.get_email_message_content(receiver, organization, team)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
end
end
end

View File

@ -21,13 +21,37 @@ module ProjectOperable
end
def add_member!(user_id, role_name='Developer')
member = members.create!(user_id: user_id)
if self.owner.is_a?(Organization)
case role_name
when 'Manager'
team = self.owner.teams.admin.take
team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = TeamUser.build(self.user_id, user_id, team.id)
when 'Developer'
team = self.owner.teams.write.take
team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = TeamUser.build(self.user_id, user_id, team.id)
when 'Reporter'
team = self.owner.teams.read.take
team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = TeamUser.build(self.user_id, user_id, team.id)
end
end
member = members.create!(user_id: user_id, team_user_id: team_user&.id)
set_developer_role(member, role_name)
end
def remove_member!(user_id)
member = members.find_by(user_id: user_id)
member.destroy! if member && self.user_id != user_id
team_user = TeamUser.find_by_id(member&.team_user_id)
team_user.destroy! if team_user
end
def member?(user_id)
@ -47,6 +71,28 @@ module ProjectOperable
def change_member_role!(user_id, role)
member = self.member(user_id)
if self.owner.is_a?(Organization) && member.team_user.present?
case role&.name
when 'Manager'
team = self.owner.teams.admin.take
team = team.nil? ? Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = member.team_user.update(team_id: team&.id)
when 'Developer'
team = self.owner.teams.write.take
team = team.nil? ? Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = member.team_user.update(team_id: team&.id)
when 'Reporter'
team = self.owner.teams.read.take
team = team.nil? ? Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false) : team
TeamProject.build(self.user_id, team.id, self.id)
OrganizationUser.build(self.user_id, user_id)
team_user = member.team_user.update(team_id: team&.id)
end
end
member.member_roles.last.update_attributes!(role: role)
end

View File

@ -11,23 +11,26 @@
# course_group_id :integer default("0")
# is_collect :integer default("1")
# graduation_group_id :integer default("0")
# team_user_id :integer
#
# Indexes
#
# index_members_on_course_id (course_id)
# index_members_on_project_id (project_id)
# index_members_on_team_user_id (team_user_id)
# index_members_on_user_id (user_id)
# index_members_on_user_id_and_project_id (user_id,project_id,course_id) UNIQUE
#
class Member < ApplicationRecord
belongs_to :user
# belongs_to :course, optional: true
belongs_to :project, optional: true
has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles
validates :user_id, :project_id, presence: true
end
class Member < ApplicationRecord
belongs_to :user
# belongs_to :course, optional: true
belongs_to :project, optional: true
belongs_to :team_user, optional: true
has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles
validates :user_id, :project_id, presence: true
end

View File

@ -31,8 +31,6 @@ class MessageTemplate < ApplicationRecord
self.create(type: 'MessageTemplate::OrganizationJoined', sys_notice: '你已加入 <b>{organization}</b> 组织', notification_url: '{baseurl}/{login}', email: email_html, email_title: 'GitLink: 你已加入 {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: 'GitLink: 你已被移出 {organization} 组织')
email_html = File.read("#{email_template_html_dir}/organization_role.html")
self.create(type: 'MessageTemplate::OrganizationRole', sys_notice: '组织 <b>{organization}</b> 已把你的角色改为 <b>{role}</b>', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', 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}')
@ -66,6 +64,10 @@ class MessageTemplate < ApplicationRecord
self.create(type: 'MessageTemplate::PullRequestJournal', sys_notice: '{nickname}评论合并请求{title}<b>{notes}</b>', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/pull_request_merged.html")
self.create(type: 'MessageTemplate::PullRequestMerged', sys_notice: '你提交的合并请求:{title} <b>已通过</b>', email: email_html, email_title: 'GitLink: 合并请求 {title} 有状态变更', notification_url: '{baseurl}/{owner}/{identifier}/pulls/{id}')
email_html = File.read("#{email_template_html_dir}/team_joined.html")
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
email_html = File.read("#{email_template_html_dir}/team_left.html")
self.create(type: 'MessageTemplate::TeamLeft', sys_notice: '你已被移出组织 <b>{organization}</b> 的 <b>{team}</b> 团队', email: email_html, email_title: 'GitLink: 在 {organization} 组织你的账号有权限变更', notification_url: '{baseurl}/{login}')
end
def self.sys_notice

View File

@ -0,0 +1,58 @@
# == 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::TeamJoined < MessageTemplate
# MessageTemplate::TeamJoined.get_message_content(User.where(login: 'yystopf'), Organization.last, Organization.last.teams.take)
def self.get_message_content(receivers, organization, team)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{team}', team&.nickname).gsub('{role}', team&.authorize_name)
url = notification_url.gsub('{login}', organization&.login)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::TeamJoined.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, organization, role)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"]
title = email_title
title.gsub!('{organization}', organization&.real_name)
title.gsub!('{team}', team&.nickname)
title.gsub!('{role}', team&.authorize_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)
content.gsub!('{team}', team&.nickname)
content.gsub!('{role}', team&.authorize_name)
return receiver&.mail, title, content
else
return '', '', ''
end
rescue => e
Rails.logger.info("MessageTemplate::TeamJoined.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -0,0 +1,58 @@
# == 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::TeamLeft < MessageTemplate
# MessageTemplate::TeamLeft.get_message_content(User.where(login: 'yystopf'), Organization.last, Organization.last.teams.take)
def self.get_message_content(receivers, organization, team)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["Normal::Permission"]
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{organization}', organization&.real_name).gsub('{team}', team&.nickname).gsub('{role}', team&.authorize_name)
url = notification_url.gsub('{login}', organization&.login)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::TeamLeft.get_message_content [ERROR] #{e}")
return '', '', ''
end
def self.get_email_message_content(receiver, organization, team)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::Permission"]
title = email_title
title.gsub!('{organization}', organization&.real_name)
title.gsub!('{team}', team&.nickname)
title.gsub!('{role}', team&.authorize_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)
content.gsub!('{team}', team&.nickname)
content.gsub!('{role}', team&.authorize_name)
return receiver&.mail, title, content
else
return '', '', ''
end
rescue => e
Rails.logger.info("MessageTemplate::TeamLeft.get_email_message_content [ERROR] #{e}")
return '', '', ''
end
end

View File

@ -56,10 +56,10 @@ class Team < ApplicationRecord
def authorize_name
case self.authorize
when 'read' then '报告者'
when 'write' then '开发者'
when 'read' then '读取'
when 'write' then '写入'
when 'admin' then '管理员'
when 'owner' then '拥有者'
when 'owner' then '管理员'
else
''
end

View File

@ -22,9 +22,17 @@ class TeamUser < ApplicationRecord
belongs_to :team, counter_cache: :num_users
belongs_to :user
has_one :member
validates :user_id, uniqueness: {scope: [:organization_id, :team_id]}
before_destroy :remove_project_member
def self.build(organization_id, user_id, team_id)
self.create!(organization_id: organization_id, user_id: user_id, team_id: team_id)
end
def remove_project_member
member.destroy if member.present?
end
end

View File

@ -786,7 +786,7 @@ class User < Owner
end
def profile_is_completed?
self.nickname.present? && self.gender.present? && self.mail.present? && self.custom_department.present?
self.nickname.present? && self.mail.present?
end
protected

View File

@ -55,7 +55,12 @@ class Gitea::Repository::Entries::CreateService < Gitea::ClientService
when 201 then success(json_parse!(body))
when 403 then error("你没有权限操作!")
when 404 then error("你操作的链接不存在!")
when 422 then error("#{filepath}文件已存在,不能重复创建!")
when 422
if @body[:new_branch].include?('/') || @body[:new_branch].include?('\'') || @body[:new_branch].include?('^') || @body[:new_branch].include?('*')
error("不合法的分支名称!")
else
error("#{filepath}文件已存在,不能重复创建!")
end
else error("系统错误!")
end
end

View File

@ -13,6 +13,7 @@ json.tracker @issue.tracker.try(:name)
json.issue_status @issue.issue_status.try(:name)
json.priority @issue.priority.try(:name)
json.version @issue.version.try(:name)
json.version_id @issue.version.try(:id)
json.issue_tags @issue.get_issue_tags
json.done_ratio @issue.done_ratio.to_s + "%"
json.issue_type @issue.issue_type

View File

@ -6,6 +6,13 @@ json.user_name trend.user.try(:show_real_name)
json.user_login trend.user.login
json.user_avatar url_to_avatar(trend.user)
json.action_time time_from_now(trend.created_at)
json.project do
json.owner do
json.partial! 'users/user_simple', locals: {user: trend&.project&.owner}
end
json.identifier trend&.project&.identifier
json.description trend&.project&.description
end
if trend.trend_type == "Issue"
json.partial! "issues/simple_issue_item", locals: {issue: trend.trend}

View File

@ -1,12 +1,27 @@
json.author do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] }
end
if commit['Status'].present?
json.author do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Author']), name: commit['Author']['Name'] }
end
json.committer do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] }
end
json.timestamp render_unix_time(commit['Committer']['When'])
json.time_from_now time_from_now(commit['Committer']['When'])
json.created_at render_format_time_with_date(commit['Committer']['When'])
json.message commit['CommitMessage']
json.sha commit['Sha']
else
json.author do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['commit']['author']), name: commit['commit']['author']['name'] }
end
json.committer do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['Committer']), name: commit['Committer']['Name'] }
end
json.timestamp render_unix_time(commit['Committer']['When'])
json.time_from_now time_from_now(commit['Committer']['When'])
json.created_at render_format_time_with_date(commit['Committer']['When'])
json.message commit['CommitMessage']
json.sha commit['Sha']
json.committer do
json.partial! 'repositories/commit_author', locals: { user: render_cache_commit_author(commit['commit']['committer']), name: commit['commit']['committer']['name'] }
end
json.timestamp render_unix_time(commit['commit']['committer']['date'])
json.time_from_now time_from_now(commit['commit']['committer']['date'])
json.created_at render_format_time_with_date(commit['commit']['committer']['date'])
json.message commit['commit']['message']
json.sha commit['sha']
end

View File

@ -0,0 +1,5 @@
class AddTeamUserToMembers < ActiveRecord::Migration[5.2]
def change
add_reference :members, :team_user
end
end

View File

@ -0,0 +1,47 @@
<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="{baseurl}"><img src="{baseurl}/images/email_logo.png" 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><a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{team}</a> 团队,拥有{role}权限
</p>
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
</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;">GitLink团队</p>
<div style="clear:both; overflow:hidden;"></div>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
<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="{baseurl}"><img src="{baseurl}/images/email_logo.png" 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><a href="{baseurl}/{login}" style="font-weight:bold;color:#3b94d6;">{team}</a> 团队
</p>
<div style="width: 100%; border-top: 1px solid #ddd; margin:10px 0;"></div>
</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;">GitLink团队</p>
<div style="clear:both; overflow:hidden;"></div>
</div>
</div>
</div>
</body>
</html>