Merge pull request '20220303版本' (#303) from Trustie/forgeplus:trustie_server into master

This commit is contained in:
xxq250 2022-03-03 15:33:17 +08:00
commit 9a8a0b4c5d
45 changed files with 1282 additions and 1037 deletions

View File

@ -192,7 +192,9 @@ class AccountsController < ApplicationController
sync_params = {
password: params[:password].to_s,
email: @user.mail
email: @user.mail,
login_name: @user.name,
source_id: 0
}
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)

View File

@ -0,0 +1,21 @@
class NoticesController < ApplicationController
def create
tip_exception("参数有误") if params["source"].blank?
user_id = params[:user_id]
if params["source"] == "CompetitionBegin"
competition_id = params[:competition_id]
SendTemplateMessageJob.perform_later('CompetitionBegin', user_id, competition_id)
elsif params["source"] == "CompetitionResult"
competition_id = params[:competition_id]
SendTemplateMessageJob.perform_later('CompetitionResult', user_id, competition_id)
elsif params["source"] == "CompetitionReview"
competition_id = params[:competition_id]
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
else
tip_exception("#{params["source"]}未配置")
end
render_ok
end
end

View File

@ -22,9 +22,9 @@ class Users::TemplateMessageSettingsController < Users::BaseController
def get_current_setting
@current_setting = @_observed_user.user_template_message_setting
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
@current_setting.notification_body.merge!(UserTemplateMessageSetting.init_notification_body.except(*@current_setting.notification_body.keys))
@current_setting.email_body.merge!(UserTemplateMessageSetting.init_email_body.except(*@current_setting.email_body.keys))
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
end
def setting_params

View File

@ -7,6 +7,8 @@ class CacheAsyncClearJob < ApplicationJob
Cache::V2::ProjectCommonService.new(id).clear
when "owner_common_service"
Cache::V2::OwnnerCommonService.new(id).clear
when "project_rank_service"
Cache::V2::ProjectRankService.new(id).clear
end
end
end

View File

@ -52,6 +52,10 @@ class SendTemplateMessageJob < ApplicationJob
receivers = User.where(id: [issue&.assigned_to_id, issue&.author_id])
receivers_string, content, notification_url = MessageTemplate::IssueExpire.get_message_content(receivers, issue)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {issue_id: issue.id})
receivers.find_each do |receiver|
receivers_email_string, email_title, email_content = MessageTemplate::IssueExpire.get_email_message_content(receiver, issue)
Notice::Write::EmailCreateService.call(receivers_email_string, email_title, email_content)
end
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)
@ -322,6 +326,30 @@ class SendTemplateMessageJob < ApplicationJob
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
when 'CompetitionBegin'
user_id, competition_id = args[0], args[1]
user = User.find_by_id(user_id)
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
return unless user.present? && project.present?
receivers = User.where(id: user_id)
receivers_string, content, notification_url = MessageTemplate::CompetitionBegin.get_message_content(receivers, project.first)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
when 'CompetitionReview'
user_id, competition_id = args[0], args[1]
user = User.find_by_id(user_id)
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
return unless user.present? && project.present?
receivers = User.where(id: user_id)
receivers_string, content, notification_url = MessageTemplate::CompetitionReview.get_message_content(receivers, project.first)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
when 'CompetitionResult'
user_id, competition_id = args[0], args[1]
user = User.find_by_id(user_id)
project = Project.find_by_sql("select *,title as name from competitions where id=#{competition_id}")
return unless user.present? && project.present?
receivers = User.where(id: user_id)
receivers_string, content, notification_url = MessageTemplate::CompetitionResult.get_message_content(receivers, project.first)
Notice::Write::CreateService.call(receivers_string, content, notification_url, source, {user_id: user_id, competition_name: project.first&.name, identifier: project.first&.identifier})
end
end
end

View File

@ -76,7 +76,7 @@ class Issue < ApplicationRecord
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
scope :closed, ->{where(status_id: 5)}
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
after_save :change_versions_count
after_save :change_versions_count, :send_update_message_to_notice_system
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
def incre_project_common
@ -200,4 +200,8 @@ class Issue < ApplicationRecord
self.project.decrement!(:closed_issues_count) if self.status_id == 5
end
def send_update_message_to_notice_system
SendTemplateMessageJob.perform_later('IssueExpire', self.id) if Site.has_notice_menu? && self.due_date == Date.today + 1.days
end
end

View File

@ -74,6 +74,11 @@ class MessageTemplate < ApplicationRecord
self.create(type: 'MessageTemplate::TeamJoined', sys_notice: '你已被拉入组织 <b>{organization}</b> 的 <b>{team}</b> 团队,拥有<b>{role}</b>权限', email: email_html, email_title: "#{PLATFORM}: 在 {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: "#{PLATFORM}: 在 {organization} 组织你的账号有权限变更", notification_url: '{baseurl}/{login}')
# 竞赛通知
self.create(type: 'MessageTemplate::CompetitionBegin', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入比赛进行阶段,可在此期间提交作品', notification_url: '{to_url}')
self.create(type: 'MessageTemplate::CompetitionResult', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 已进入成绩公示阶段,可查看排行榜信息', notification_url: '{to_url}')
self.create(type: 'MessageTemplate::CompetitionReview', sys_notice: '你报名的竞赛 <b>{competition_name}</b> 距作品提交结束日期仅剩3天若尚未提交参赛作品请尽快提交', notification_url: '{to_url}')
end
def self.sys_notice

View File

@ -0,0 +1,35 @@
# == 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)
#
# 报名的竞赛进入比赛进行阶段
# 触发场景
# 赛队成员报名的竞赛已进入比赛进行阶段
# 通知文案格式
# 你报名的竞赛 xxx 已进入比赛进行阶段,可在此阶段提交作品
# 时间x分钟/小时/天/月前
# 通知文案示例
# 你报名的竞赛 代码审查大赛 已进入比赛进行阶段,可在此期间提交作品
# 时间3小时前
# 点击通知跳转页面
# 点击此通知将跳转到代码审查大赛详情页:
# http://117.50.100.12:8080/competitions/lgw7st/home
class MessageTemplate::CompetitionBegin < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, competition)
return receivers_string(receivers), sys_notice.to_s.gsub('{competition_name}', competition&.name), notification_url.to_s.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
# rescue
# return '', '', ''
end
end

View File

@ -0,0 +1,35 @@
# == 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)
#
# 报名的竞赛进入成绩公示阶段
# 触发场景
# 赛队成员报名的竞赛已进入成绩公示阶段
# 通知文案格式
# 你报名的竞赛 xxx 已进入成绩公示阶段,可查看排行榜信息
# 时间x分钟/小时/天/月前
# 通知文案示例
# 你报名的竞赛 代码审查大赛 已进入成绩公示阶段,可查看排行榜信息
# 时间3小时前
# 点击通知跳转页面
# 点击此通知将跳转到代码审查大赛详情页:
# http://117.50.100.12:8080/competitions/lgw7st/home
class MessageTemplate::CompetitionResult < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, competition)
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
rescue
return '', '', ''
end
end

View File

@ -0,0 +1,35 @@
# == 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)
#
# 报名的竞赛比赛结束时间临近
# 触发场景
# 赛队成员报名的竞赛阶段处于比赛进行中且距比赛结束日期仅剩3天
# 通知文案格式
# 你报名的竞赛 xxx 距作品提交结束日期仅剩3天若尚未提交参赛作品请尽快提交
# 时间x分钟/小时/天/月前
# 通知文案示例
# 你报名的竞赛 代码审查大赛 距作品提交结束日期仅剩3天若尚未提交参赛作品请尽快提交
# 时间3小时前
# 点击通知跳转页面
# 点击此通知将跳转到代码审查大赛详情页:
# http://117.50.100.12:8080/competitions/lgw7st/home
class MessageTemplate::CompetitionReview < MessageTemplate
# MessageTemplate::FollowedTip.get_message_content(User.where(login: 'yystopf'), User.last)
def self.get_message_content(receivers, competition)
return receivers_string(receivers), sys_notice.gsub('{competition_name}', competition&.title), notification_url.gsub('{to_url}', "/competitions/#{competition.identifier}/home")
rescue
return '', '', ''
end
end

View File

@ -16,18 +16,21 @@
class MessageTemplate::IssueExpire < MessageTemplate
# MessageTemplate::IssueCreatorExpire.get_message_content(User.where(login: 'yystopf'), Issue.last)
def self.get_message_content(receiver, issue)
def self.get_message_content(receivers, issue)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::IssueExpire"]
send_setting = receiver.user_template_message_setting.notification_body["CreateOrAssign::IssueExpire"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["CreateOrAssign::IssueExpire"] : send_setting
receivers = receivers.where.not(id: receiver.id) unless send_setting
end
end
return '', '', '' if receivers.blank?
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
else
return '', '', ''
end
rescue => e
Rails.logger.info("MessageTemplate::IssueExpire.get_message_content [ERROR] #{e}")
return '', '', ''
@ -35,9 +38,12 @@ class MessageTemplate::IssueExpire < MessageTemplate
def self.get_email_message_content(receiver, issue)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["Normal::IssueExpire"]
send_setting = receiver.user_template_message_setting.email_body["CreateOrAssign::IssueExpire"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["CreateOrAssign::IssueExpire"] : send_setting
return '', '', '' unless send_setting
project = issue&.project
owner = project&.owner
title = email_title
content = email
content.gsub!('{receiver}', receiver&.real_name)

View File

@ -19,12 +19,14 @@ class MessageTemplate::ProjectForked < MessageTemplate
def self.get_message_content(receivers, user, project)
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["ManageProject::Forked"]
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Forked"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Forked"] : send_setting
receivers = receivers.where.not(id: receiver.id) unless send_setting
end
end
return '', '', '' if receivers.blank?
content = sys_notice.gsub('{nickname1}', user&.real_name).gsub('{nickname2}', project&.owner&.real_name).gsub('{repository}', project&.name)
url = notification_url.gsub('{login}', user&.login).gsub('{identifier}', project&.identifier)
url = notification_url.gsub('{owner}', user&.login).gsub('{identifier}', project&.identifier)
return receivers_string(receivers), content, url
rescue => e
Rails.logger.info("MessageTemplate::ProjectForked.get_message_content [ERROR] #{e}")

View File

@ -19,6 +19,8 @@ class MessageTemplate::ProjectMilestone < MessageTemplate
def self.get_message_content(receivers, operator, milestone)
receivers.each do |receiver|
if receiver.user_template_message_setting.present?
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Milestone"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Milestone"] : send_setting
receivers = receivers.where.not(id: receiver.id) unless receiver.user_template_message_setting.notification_body["ManageProject::Milestone"]
end
end
@ -36,7 +38,9 @@ class MessageTemplate::ProjectMilestone < MessageTemplate
def self.get_email_message_content(receiver, operator, milestone)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::Milestone"]
send_setting = receiver.user_template_message_setting.email_body["ManageProject::Milestone"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::Milestone"] : send_setting
return '', '', '' unless send_setting
project = milestone&.project
owner = project&.owner
title = email_title

View File

@ -19,7 +19,9 @@ class MessageTemplate::ProjectMilestoneCompleted < MessageTemplate
def self.get_message_content(receivers, milestone)
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["ManageProject::MilestoneCompleted"]
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::MilestoneCompleted"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::MilestoneCompleted"] : send_setting
receivers = receivers.where.not(id: receiver.id) unless send_setting
end
end
return '', '', '' if receivers.blank?
@ -36,7 +38,9 @@ class MessageTemplate::ProjectMilestoneCompleted < MessageTemplate
def self.get_email_message_content(receiver, milestone)
if receiver.user_template_message_setting.present?
return '', '', '' unless receiver.user_template_message_setting.email_body["ManageProject::MilestoneCompleted"]
send_setting = receiver.user_template_message_setting.email_body["ManageProject::MilestoneCompleted"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_email_body["ManageProject::MilestoneCompleted"] : send_setting
return '', '', '' unless send_setting
project = milestone&.project
owner = project&.owner
title = email_title

View File

@ -19,7 +19,9 @@ class MessageTemplate::ProjectPraised < MessageTemplate
def self.get_message_content(receivers, user, project)
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["ManageProject::Praised"]
send_setting = receiver.user_template_message_setting.notification_body["ManageProject::Praised"]
send_setting = send_setting.nil? ? UserTemplateMessageSetting.init_notification_body["ManageProject::Praised"] : send_setting
receivers = receivers.where.not(id: receiver.id) unless send_setting
end
end
return '', '', '' if receivers.blank?

View File

@ -125,8 +125,8 @@ class Project < ApplicationRecord
has_many :has_pinned_users, through: :pinned_projects, source: :user
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
after_create :incre_user_statistic, :incre_platform_statistic
after_save :check_project_members, :reset_cache_data
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned
after_save :check_project_members
before_save :set_invite_code, :reset_unmember_followed, :set_recommend_and_is_pinned, :reset_cache_data
before_destroy :decre_project_common, :decre_forked_from_project_count
after_destroy :decre_user_statistic, :decre_platform_statistic
scope :project_statics_select, -> {select(:id,:name, :is_public, :identifier, :status, :project_type, :user_id, :forked_count, :description, :visits, :project_category_id, :project_language_id, :license_id, :ignore_id, :watchers_count, :created_on)}
@ -150,7 +150,7 @@ class Project < ApplicationRecord
end
def reset_cache_data
CacheAsyncResetJob.perform_later("project_common_service", self.id)
CacheAsyncResetJob.set(wait: 5.seconds).perform_later("project_common_service", self.id)
if changes[:user_id].present?
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: -1}, changes[:user_id].first)
CacheAsyncSetJob.perform_later("user_statistic_service", {project_count: 1}, changes[:user_id].last)
@ -163,6 +163,14 @@ class Project < ApplicationRecord
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: first_language&.name, project_language_count: -1})
CacheAsyncSetJob.perform_later("platform_statistic_service", {project_language_count_key: last_language&.name, project_language_count: 1})
end
if changes[:is_public].present?
if changes[:is_public][0] && !changes[:is_public][1]
CacheAsyncClearJob.perform_later('project_rank_service', self.id)
end
if !changes[:is_public][0] && changes[:is_public][1]
$redis_cache.srem("v2-project-rank-deleted", self.id)
end
end
end
def decre_project_common

View File

@ -16,15 +16,15 @@ class Cache::V2::UserDateRankService < ApplicationService
end
def read_rank
user_rank
user_rank unless @user_id.blank?
end
def read_statistic
user_statistic
user_statistic unless @user_id.blank?
end
def call
set_user_rank
set_user_rank unless @user_id.blank?
end
private

View File

@ -33,10 +33,9 @@ class Projects::ForkService < ApplicationService
new_repository.update_column('url', result['clone_url']) if result
ForkUser.create(project_id: @project.id, fork_project_id: clone_project.id, user_id: clone_project.user_id)
SendTemplateMessageJob.perform_later('ProjectForked', @target_owner.id, @project.id) if Site.has_notice_menu?
clone_project
SendTemplateMessageJob.perform_later('ProjectForked', @target_owner.id, @project.id) if Site.has_notice_menu?
end
rescue => e
puts "clone project service error: #{e.message}"

View File

@ -1,7 +1,7 @@
json.count @forks_count
json.users do
json.array! @fork_users.each do |f|
user = f.user
user = f.user.present? ? f.user : Organization.find_by(id: f.user_id)
json.id f.fork_project.id
json.identifier f.fork_project.identifier
json.name "#{user.try(:show_real_name)}/#{f.fork_project.try(:name)}"

View File

@ -9,7 +9,6 @@ Rails.application.routes.draw do
# Serve websocket cable requests in-process
mount ActionCable.server => '/cable'
get 'attachments/entries/get_file', to: 'attachments#get_file'
get 'attachments/download/:id', to: 'attachments#show'
get 'attachments/download/:id/:filename', to: 'attachments#show'
@ -385,6 +384,7 @@ Rails.application.routes.draw do
resource :bind_user, only: [:create]
resources :hot_keywords, only: [:index]
resources :notices, only: [:create]
namespace :weapps do
resource :home, only: [:show]

View File

@ -0,0 +1,38 @@
# 竞赛通知
namespace :competition_notice do
desc "竞赛通知-进入提交作品状态"
task submit_work_begin: :environment do
competitions = Project.find_by_sql("select * from competitions where status=1 and DATE_FORMAT(enroll_end_time,'%Y-%m-%d %h:00:00') ='#{(Time.now - 1.day).strftime('%Y-%m-%d %H:00:00')}' ")
competitions.each do |c|
competition_teams = Project.find_by_sql("select * from competition_teams where competition_id=#{c.id} ")
competition_teams.each do |team|
SendTemplateMessageJob.perform_later('CompetitionBegin', team.user_id, c.id)
end
end
end
desc "竞赛通知-截止提交作品时间前3小时"
task submit_work_end: :environment do
competitions = Project.find_by_sql("select * from competitions where status=1 and DATE_FORMAT(end_time,'%Y-%m-%d %h:00:00') ='#{(Time.now + 3.hours).strftime('%Y-%m-%d %H:00:00')}' ")
competitions.each do |c|
competition_teams = Project.find_by_sql("select * from competition_teams where competition_id=#{c.id} ")
competition_teams.each do |team|
SendTemplateMessageJob.perform_later('CompetitionReview', team.user_id, c.id)
end
end
end
desc "竞赛通知-报名的竞赛进入成绩公示阶段"
task submit_work_result: :environment do
competitions = Project.find_by_sql("select * from competitions where status=1 and DATE_FORMAT(review_time,'%Y-%m-%d %h:00:00') ='#{(Time.now - 1.day).strftime('%Y-%m-%d %H:00:00')}' ")
competitions.each do |c|
competition_teams = Project.find_by_sql("select * from competition_teams where competition_id=#{c.id} ")
competition_teams.each do |team|
SendTemplateMessageJob.perform_later('CompetitionResult', team.user_id, c.id)
end
end
end
end

View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="88" viewBox="0 0 400 88">
<defs>
<linearGradient id="linear-gradient" y1="0.501" x2="1" y2="0.501" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#6dffff"/>
<stop offset="1" stop-color="#0080ff"/>
</linearGradient>
</defs>
<g id="logo" transform="translate(-181 -101)">
<rect id="矩形_1" data-name="矩形 1" width="400" height="88" transform="translate(181 101)" fill="#fff" opacity="0"/>
<g id="顶部logo" transform="translate(181.055 106.72)">
<path id="形状" d="M64.185,77.408H51.334V0h8.379V69.74h4.473v7.668Zm10.223-8.6,0,0-6.029-3.653V10.536l6.033-3.655V68.809Zm-38.624-.144V17.273l-3.337-1.217V6.881l12.71,7.382v6.953L41.891,20V65.511l-6.1,3.152ZM22.152,60.493V17.059L28.9,20.427v36.7l-6.742,3.365Zm69.793,0h0l-3.051-.5L85.2,53.9v3.941l-2.343-1.217V20.856l2.84-1.433,3.265,4.445-.072-5.734,3.054-1.147V60.493ZM.072,57.841H0V23.295l14.626,4.874v5.806L5.68,32.326V47.52L10.508,45.3V40.5H7.74V35.551l6.957.715V50.388L.073,57.84Zm120.7-.142h-.005l-9.226-.432-5.678-7.382v4.946l-5.894-1.219V27.881l5.894-1.433v4.8l5.325-7.169,8.021-.859L108.417,40.354l12.351,17.341Z" transform="translate(0 0)" fill="url(#linear-gradient)"/>
<path id="形状-2" data-name="形状" d="M192.836,66.37l0,0-1.63-1.215a16.1,16.1,0,0,0,1.136-2.222A15.2,15.2,0,0,0,193,61.32c.04-.111.08-.22.12-.326a12.573,12.573,0,0,0,.567-1.934l1.918.5a4.741,4.741,0,0,0-.142.646c-.066.2-.132.414-.205.652-.085.276-.179.58-.292.925a22.742,22.742,0,0,1-.852,2.15,27.108,27.108,0,0,1-1.278,2.434ZM64.824,66.3h0l-.991-.356-.924-.358c.142-.571.253-1.115.351-1.595.051-.248.1-.482.146-.7.085-.423.144-.847.207-1.3.044-.318.09-.645.148-1l.01-.12c.068-.806.132-1.567.132-2.388V50.6h6.888l1.491-2.222H66.1c-.237.359-.453.677-.645.957-.154.226-.294.43-.419.62-.1.124-.188.23-.263.32-.146.174-.234.279-.234.326l-1.491-1.5c.418-.565.851-1.148,1.136-1.577.172-.3.369-.607.578-.927.137-.211.277-.425.416-.65a14.379,14.379,0,0,0,.713-1.361c.071-.149.14-.293.209-.432l1.777,1a3.542,3.542,0,0,1-.31.7c-.042.079-.082.157-.118.229h7.668v1.718L73.272,50.53h1.136V50.1H76.4V63.646a2.617,2.617,0,0,1-.639,1.793,2.039,2.039,0,0,1-1.633.718H72.989V63.934h1.136c.191,0,.283-.117.283-.358V61.712H71v3.943H69.013V61.712H65.676c-.043.386-.11.738-.174,1.08-.043.226-.083.439-.112.641a8.225,8.225,0,0,1-.173.91c-.042.181-.082.352-.11.522-.071.437-.143.725-.214,1a2.19,2.19,0,0,0-.07.426Zm6.105-9.317v2.58h3.409v-2.58Zm-5.042.072v2.508h3.054V57.053Zm5.042-4.3v2.006h3.409V52.752Zm-5.042,0v2.006h3.054V52.752ZM188.649,66.3l0,0-1.7-1.142c.058-.118.128-.272.209-.45.117-.256.262-.574.429-.913.288-.584.575-1.234.852-1.934a15.544,15.544,0,0,0,.611-1.811q.05-.172.1-.339a7.222,7.222,0,0,0,.283-2.006V44.511h15.62v2.22h-13.7V57.555a8.817,8.817,0,0,1-.211,1.862,19.834,19.834,0,0,1-.5,1.937c-.208.627-.418,1.192-.622,1.738l-.019.052a16.993,16.993,0,0,1-.639,1.577c-.113.231-.207.442-.29.628-.073.162-.141.314-.206.447a2.02,2.02,0,0,0-.211.5Zm14.554-.07v0l-2.342-6.449,1.777-.862,2.413,6.451-1.844.86Zm-6.036,0h-1.491V64.006h1.491a.259.259,0,0,0,.214-.072.266.266,0,0,0,.072-.216V58.486h-4.828V48.953h3.123l1.208-2.222,1.7,1.219-.567,1h4.189v-.5h1.988v7.526a2.635,2.635,0,0,1-.639,1.793,2,2,0,0,1-1.442.726,1.727,1.727,0,0,1-.193-.011H199.44v5.232a2.627,2.627,0,0,1-.639,1.793A2.313,2.313,0,0,1,197.167,66.229Zm-2.554-11.182v1.289h7.382c.214,0,.286-.072.286-.286v-1Zm0-3.8v1.5h7.668v-1.5Zm-9.87,14.981h0l-1.772-.932,3.407-7.884,1.846.931-3.478,7.884Zm-124.25,0h-4.4v-9.1c-.142.214-.286.433-.425.646l-.121.183c-.1.156-.2.309-.306.46l-1.561-1.361A12.764,12.764,0,0,0,55.1,54.545l.012-.029c.345-.837.7-1.7.912-2.409.2-.746.339-1.293.5-1.934a5.114,5.114,0,0,0,.211-1V47.376H54.812V45.154h8.237v2.222h-4.4v2.078c0,.048-.032.224-.1.575-.032.174-.071.386-.117.644a22.027,22.027,0,0,1-.78,2.8h3.123v-.43h1.988V63.718a2.617,2.617,0,0,1-.639,1.793A2.039,2.039,0,0,1,60.493,66.229ZM57.936,55.762v8.316h2.415c.212,0,.283-.073.283-.288V55.762ZM167.774,66.157h-1.988V56.05h-8.379a17.373,17.373,0,0,1-1.064,3.869c-.455,1.111-.906,2.189-1.421,3.154-.518.9-.935,1.6-1.277,2.15-.528.62-.639.811-.639.862l-1.563-1.433c.007-.01.215-.289.5-.718.292-.443.671-1.135,1.066-1.865a24.842,24.842,0,0,0,1.277-2.722,23.343,23.343,0,0,0,1.064-3.37h-5.181V53.756h5.467a1.614,1.614,0,0,0,.07-.574V47.235h-4.045V45.012h19.6v2.222h-3.479v6.593h5.042V56.05h-5.042V66.157ZM157.691,47.235v5.947a1.447,1.447,0,0,0-.07.574h8.093V47.235ZM87.9,66.157h0v0l-.281-1.073-.283-1.075a5.866,5.866,0,0,0,.78-.288c.449-.193,1.022-.45,1.918-.859.636-.321,1.448-.79,2.485-1.433a17.173,17.173,0,0,0,2.626-2.009H87.259V57.2h9.87a13.358,13.358,0,0,0,.78-1.363,8.376,8.376,0,0,0,.569-1.433v-4.73h1.988V54.9a6,6,0,0,1-.994,2.294H109.2v2.22h-8.1l7.882,4.8-.993,1.934-8.452-5.16.783-1.577h-2.2A18.535,18.535,0,0,1,96.063,61.5c-.605.49-1.325,1.03-2.2,1.649a16.9,16.9,0,0,1-2.132,1.291c-.247.125-.475.248-.694.368a9.545,9.545,0,0,1-1.152.563,10.6,10.6,0,0,1-1.066.463c-.1.038-.193.074-.281.11A2.943,2.943,0,0,1,87.9,66.157Zm40.328-4.946a3.976,3.976,0,0,1-3.9-3.943,3.905,3.905,0,1,1,7.81,0A3.977,3.977,0,0,1,128.226,61.21ZM94.572,56.765h0l-5.322-2.435.711-2.078,5.325,2.436-.71,2.076Zm165.006-.358H218.966V54.831h40.612v1.577Zm-218.469,0H.5V54.831H41.109v1.577Zm145.764-.5,0,0-3.618-3.725,1.277-1.649,3.692,3.727L186.874,55.9ZM96.845,54.044h0L91.52,51.533l.78-2.078,5.325,2.58-.779,2.006Zm-7.457-2.8H87.4V46.373h9.942L96.7,45.012l1.774-1,1.064,2.436h7.526v-.43h1.988v5.16h-1.988V48.6H89.388v2.652Zm97.484-1.291,0,0-3.69-3.725,1.28-1.646,3.692,3.725-1.278,1.646ZM25.985,33.9H0V.144H41.394l-2.557,4.37v.072h-26.7V29.53h17.4v-11.9H20.8V13.188H41.25V33.9l-11.713,0V30.319L25.986,33.9Zm207.676-.07h0l-11.356,0V.072h11.358v18.2l11.005-8.17h14.059L245.732,20.141l12.706,13.685-12.706,0L233.661,21.217V33.833Zm-66.1,0H156.2V10.106h11.36V33.831Zm-24.354,0h-31.1V.072h11.857V29.458h21.725l-2.484,4.372Zm-44.587,0H79.946V14.407H73.911V10.178h6.036V2.436h11.36v7.742H101.6l-2.84,4.229H91.307V29.746h9.8L98.62,33.829Zm-35.287,0H51.972V10.106h11.36V33.831Zm148.39-.144H200.5V10.034l-3.9,4.229h-7.1V33.687H178.141V10.034h33.582V33.687ZM167.56,7.31H156.2V0h11.36V7.31Zm-104.228,0H51.972V0h11.36V7.31Z" transform="translate(140.368 8.673)" fill="#fffdfd"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>

View File

@ -24,7 +24,7 @@
<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>
<a href="{baseurl}"><img src="{baseurl}/images/email_logo.svg" height="45" ></a>
<p style="color:#fff; float:right; margin-top:15px;">确实开源,协同创新</p>
<div style="clear:both; overflow:hidden;"></div>
</div>