Merge branch 'dev_auth' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_auth

dev_auth
杨树林 5 years ago
commit fde9accae5

@ -60,7 +60,7 @@ class Admins::CompetitionStagesController < Admins::BaseController
end
# 如果计算的是最后一个阶段,则同时计算总成绩(只有一个阶段则不需计算)
if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size != 0
if current_stage.max_end_time == current_competition.max_stage_end_time && current_competition.competition_stages.size > 1
calculate_total_score current_competition
end
end
@ -174,6 +174,7 @@ class Admins::CompetitionStagesController < Admins::BaseController
end
def calculate_total_score competition
competition.competition_scores.where(competition_stage_id: 0).destroy_all
competition.competition_teams.each do |team|
total_score = 0
total_time = 0
@ -183,8 +184,11 @@ class Admins::CompetitionStagesController < Admins::BaseController
total_score += stage_score.try(:score).to_f * stage.score_rate
total_time += stage_score.try(:cost_time).to_i
end
CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id,
competition_stage_id: 0, score: total_score, cost_time: total_time)
unless team.competition_scores.exists?(competition_id: competition.id, competition_stage_id: 0)
CompetitionScore.create!(user_id: team.user_id, competition_team_id: team.id, competition_id: competition.id,
competition_stage_id: 0, score: total_score, cost_time: total_time)
end
end
end
end

@ -7,7 +7,7 @@ class Competitions::CompetitionModulesController < Competitions::BaseController
@modules = current_competition.unhidden_competition_modules.order(position: :asc)
# 未登录、未获奖用户,不展示获奖证书栏目
if !current_user.logged? || !current_competition.competition_prize_users.exists?(user: current_user)
if !current_user.logged? || !current_competition.finished? || !current_competition.competition_prize_users.exists?(user: current_user)
@modules = @modules.select { |mod| mod.name != '获奖证书' }
end
end

@ -44,6 +44,12 @@ class Competitions::CompetitionsController < Competitions::BaseController
def common_header
@competition = current_competition
@competition_modules = @competition.unhidden_competition_modules
# 未登录、未获奖用户,不展示获奖证书栏目
if !current_user.logged? || !current_competition.finished? || !current_competition.competition_prize_users.exists?(user: current_user)
@competition_modules = @competition_modules.select { |mod| mod.name != '获奖证书' }
end
@user = current_user
current_competition.increment!(:visits)
@ -113,6 +119,8 @@ class Competitions::CompetitionsController < Competitions::BaseController
@competition = current_competition
if params[:stage_id]
@stage = @competition.competition_stages.find_by(id: params[:stage_id])
elsif @competition.competition_stages.count == 1
@stage = @competition.competition_stages.take
end
@records = @competition.competition_teams.joins(:competition_scores).where(competition_scores: {competition_stage_id: @stage&.id.to_i})

@ -39,9 +39,11 @@ module CompetitionsHelper
stages = []
statistic_stages = competition.competition_stages.where("score_rate > 0")
end_time = competition.max_stage_end_time || competition.end_time
if end_time && end_time < Time.now
stages << {id: nil, name: statistic_stages.size > 1 ? "总排行榜" : "排行榜", rate: 1.0, start_time: competition.start_time, end_time: competition.end_time}
unless statistic_stages.size == 1
end_time = competition.max_stage_end_time || competition.end_time
if end_time && end_time < Time.now
stages << {id: nil, name: statistic_stages.size > 1 ? "总排行榜" : "排行榜", rate: 1.0, start_time: competition.start_time, end_time: competition.end_time}
end
end
statistic_stages.each do |stage|

@ -0,0 +1,5 @@
module PdfkitHelper
def download_image(url)
'data:image/png;base64,' + Base64.encode64(open(url) { |io| io.read })
end
end

@ -0,0 +1,19 @@
# 生成竞赛个人证书Job
class GenerateCompetitionPersonalCertificateJob < ApplicationJob
queue_as :default
def perform(prize_user_id)
@prize_user = CompetitionPrizeUser.find_by(id: prize_user_id)
return if @prize_user.blank? || @prize_user.certificate_exist?
template = @prize_user.user.is_teacher? ? 'teacher' : 'personal'
file = File.open(Rails.root.join("app/templates/competition_certificates/#{template}.html.erb"))
html = ERB.new(file.read).result(binding)
kit = PDFKit.new(html, page_width: 842, page_height: 595)
path = @prize_user.certificate_path
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless File.directory?(dir)
kit.to_pdf(path)
end
end

@ -0,0 +1,24 @@
# 生成竞赛团体证书Job
class GenerateCompetitionTeamCertificateJob < ApplicationJob
queue_as :default
def perform(competition_team_id)
@team = CompetitionTeam.find_by(id: competition_team_id)
@prize = @team&.competition_prize_users&.first&.competition_prize
return if @team.blank? || !@prize.team_certificate_exists? || @team.certificate_exists?
members = @team.team_members.includes(user: :user_extension).to_a
@member_names = members.select { |m| !m.user.is_teacher? }.map(&:user_name).join('、')
@teacher_names = members.select { |m| m.user.is_teacher? }.map(&:user_name).join('、')
file = File.open(Rails.root.join("app/templates/competition_certificates/team.html.erb"))
html = ERB.new(file.read).result(binding)
kit = PDFKit.new(html, page_width: 842, page_height: 595)
path = @team.certificate_path
dir = File.dirname(path)
FileUtils.mkdir_p(dir) unless File.directory?(dir)
kit.to_pdf(path)
end
end

@ -7,6 +7,30 @@ class CompetitionPrize < ApplicationRecord
enumerize :category, in: %i[bonus unset]
def member_certificate_exists?
Util::FileManage.exists?(self, self.class.member_suffix)
end
def teacher_certificate_exists?
Util::FileManage.exists?(self, self.class.teacher_suffix)
end
def team_certificate_exists?
Util::FileManage.exists?(self, self.class.team_suffix)
end
def member_certificate_path
Util::FileManage.source_disk_filename(self, self.class.member_suffix)
end
def teacher_certificate_path
Util::FileManage.source_disk_filename(self, self.class.teacher_suffix)
end
def team_certificate_path
Util::FileManage.source_disk_filename(self, self.class.team_suffix)
end
def self.member_suffix
'_member'
end

@ -13,4 +13,8 @@ class TeamMember < ApplicationRecord
def en_role
is_teacher? ? 'teacher' : 'member'
end
def user_name
user&.real_name
end
end

@ -1,26 +1,35 @@
class Admins::ApproveCompetitionPrizeUserService < ApplicationService
attr_reader :prize_user, :approver
attr_reader :competition, :prize_user, :approver
def initialize(prize_user, approver)
@prize_user = prize_user
@approver = approver
@competition = prize_user.competition
@prize_user = prize_user
@approver = approver
end
def call
raise Error, '请勿重复审批' if prize_user.approved?
raise Error, '该用户未认证完成' unless prize_user.user_certified?
prize = prize_user.competition_prize
ActiveRecord::Base.transaction do
prize_user.approve
prize_user.approver = approver
prize_user.approved_at = Time.now
prize_user.save!
if prize_user.competition_team.all_prize_approved?
# TODO: 生成团队证书
# 生成个人证书
# 是老师并且教师证书模板存在 或者是学生而且个人证书模板存在
if (prize_user.user.is_teacher? && prize.teacher_certificate_exists?) ||
(!prize_user.user.is_teacher? && prize.member_certificate_exists?)
GenerateCompetitionPersonalCertificateJob.perform_later(prize_user.id)
end
# TODO: 生成个人证书
# 生成团队证书
if !competition.personal? && prize_user.competition_team.all_prize_approved? && prize.team_certificate_exists?
GenerateCompetitionTeamCertificateJob.perform_later(prize_user.competition_team.id)
end
end
end
end

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="competition-certificate" style="position: absolute;font-size: 85px;font-family: SimSun;">
<img src="<%= ApplicationController.helpers.download_image(@prize_user.competition_prize.member_certificate_path) %>"/>
<div class="competition-certificate-body" style="position: absolute;width: 82%;top: 35%;left: 9%;">
<p><%= @prize_user.user.school_name %> <%= @prize_user.user.real_name %>(学号 <%= @prize_user.student_id %></p>
<p style="padding-left:2em;line-height: 1.8">
荣获第二届“<b>全国高校绿色计算大赛</b>”( <%= @prize_user.competition.sub_title %> )“<b>全国<%= @prize_user.competition_prize.name %></b>”。
<br/>特发此证,以资鼓励。
</p>
</div>
</div>
</body>
</html>

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="competition-certificate" style="position: absolute;font-size: 85px;font-family: SimSun;">
<img src="<%= ApplicationController.helpers.download_image(@prize_user.competition_prize.teacher_certificate_path) %>"/>
<div class="competition-certificate-body" style="position: absolute;width: 82%;top: 35%;left: 9%;">
<p><%= @prize_user.user.school_name %> <%= @prize_user.user.real_name %> 老师:</p>
<p style="text-indent:2em;line-height: 1.8;margin-bottom: 0px;">
在第二届“<b>全国高校绿色计算大赛</b>”(<%= @prize_user.competition.sub_title %>)中,带领学生团队 表现突出,成绩优异,荣获“<b>优秀指导教师</b>”称号。
</p>
<p style="text-indent:2em;line-height: 1.8;margin-top: 0px;">特发此证,以资鼓励。</p>
</div>
</div>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="competition-certificate" style="position: absolute;font-size: 85px;font-family: SimSun;">
<img src="<%= ApplicationController.helpers.download_image(@prize.team_certificate_path) %>"/>
<div class="competition-certificate-body" style="position: absolute;width: 82%;top: 35%;left: 9%;">
<p style="text-indent:2em;line-height: 1.8;margin-bottom: 0px;">
<%= @member_names %>(指导老师:<%= @teacher_names %> 在第二届“<b>全国高校绿色计算大赛</b>”(任务挑战组)中成绩突出,荣获“<b>团体 <%= @prize.name %></b>”。
</p>
<p style="text-indent:2em;line-height: 1.8;margin-top: 0px;">特发此证,以资鼓励。</p>
</div>
</div>
</body>
</html>

@ -513,7 +513,9 @@
<div class="card-header d-flex justify-content-between align-items-center">
<span class="flex-1">奖项配置</span>
<%= link_to '新增奖项', new_admins_competition_competition_prize_path(@competition), remote: true, class: 'btn btn-primary btn-sm add-competition-prize-btn' %>
<% unless @competition.competition_prize_users.exists? %>
<%= link_to '新增奖项', new_admins_competition_competition_prize_path(@competition), remote: true, class: 'btn btn-primary btn-sm add-competition-prize-btn' %>
<% end %>
<% if @competition.finished? && !@competition.competition_prize_users.exists? %>
<%= javascript_void_link '生成获奖记录', class: 'btn btn-primary btn-sm ml-2 generate-prize-user-action' %>

@ -1,29 +1,28 @@
import React, {Component} from 'react';
import React, { Component } from 'react';
import {Tabs} from 'antd';
import axios from 'axios';
import {markdownToHTML, getImageUrl, AttachmentList} from 'educoder';
import {markdownToHTML,getImageUrl,AttachmentList} from 'educoder';
import CompetitionContentspdfdownload from './CompetitionContentspdfChild/CompetitionContentspdfdownload';
import CompetitionContentspdfpeopledata from './CompetitionContentspdfChild/CompetitionContentspdfpeopledata';
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
const {TabPane} = Tabs;
class CompetitionContentspdf extends Component {
const { TabPane } = Tabs;
class CompetitionContentspdf extends Component{
constructor(props) {
super(props)
this.state = {
Tabskey: "1"
this.state={
Tabskey:"1"
}
}
componentDidMount() {
componentDidMount(){
window.document.title = '竞赛';
}
Competitioncallback = (key) => {
Competitioncallback=(key)=>{
this.setState({
Tabskey: key
Tabskey:key
})
}
@ -35,18 +34,18 @@ class CompetitionContentspdf extends Component {
<div className={"fr"}>
<div className={"mb100 "}>
<Tabs defaultActiveKey="1" onChange={(e) => this.Competitioncallback(e)} activeKey={this.state.Tabskey}>
<TabPane tab="获奖证书下载" key="1">
<CompetitionContentspdfdownload
<TabPane tab="获奖证书下载" key="1" >
{this.state.Tabskey==="1"?<CompetitionContentspdfdownload
{...this.props}
{...this.state}
Competitioncallback={(e) => this.Competitioncallback(e)}
/>
Competitioncallback={(e)=>this.Competitioncallback(e)}
/>:""}
</TabPane>
<TabPane tab="完善个人信息" key="2">
<CompetitionContentspdfpeopledata
{this.state.Tabskey==="2"?<CompetitionContentspdfpeopledata
{...this.props}
{...this.state}
/>
/>:""}
</TabPane>
</Tabs>
</div>
@ -55,5 +54,4 @@ class CompetitionContentspdf extends Component {
)
}
}
export default CompetitionContentspdf;
export default CompetitionContentspdf;

@ -1,43 +1,42 @@
import React, {Component} from 'react';
import {Button, Layout, Row, Col, Divider, Table} from 'antd';
import React, { Component } from 'react';
import {Button,Layout,Row, Col,Divider,Table} from 'antd';
import axios from 'axios';
import {getImageUrl} from 'educoder';
import './CompetitionContentspdfdownload.css';
// import NoneData from "../../../courses/shixunHomework/shixunHomework";
class CompetitionContentspdfdownload extends Component {
class CompetitionContentspdfdownload extends Component{
constructor(props) {
super(props)
this.state = {
data: undefined,
teams: undefined
this.state={
data:undefined,
teams:undefined
}
}
componentDidMount() {
componentDidMount(){
window.document.title = '竞赛';
let url = `/competitions/${this.props.match.params.identifier}/prize.json`;
let url=`/competitions/${this.props.match.params.identifier}/prize.json`;
axios.get(url).then((response) => {
if (response.status === 200) {
if(response.status===200){
let datas = response.data.teams;
if (datas.length > 0) {
datas.map((item, key) => {
let lista = item.team_members;
if (lista.length > 0) {
let datas=response.data.teams;
if(datas.length>0){
datas.map((item,key)=>{
let lista=item.team_members;
if(lista.length>0){
console.log(lista)
lista.map((i, k) => {
i["bank_account"] = item.bank_account;
lista.map((i,k)=>{
i["bank_account"]=item.bank_account;
})
}
})
}
this.setState({
data: response.data,
teams: datas,
data:response.data,
teams:datas,
})
}
}).catch((error) => {
@ -48,96 +47,88 @@ class CompetitionContentspdfdownload extends Component {
render() {
let {data, teams} = this.state;
let {data,teams}=this.state;
const columns = [
{
title: '角色',
dataIndex: 'type',
key: 'type',
render: (text, record) => (
<span>
{
title: '角色',
dataIndex: 'type',
key: 'type',
render: (text, record) => (
<span>
{record.role}
</span>
),
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
render: (text, record) => (
<span>
),
},
{
title: '姓名',
dataIndex: 'name',
key: 'name',
render: (text, record) => (
<span>
{record.name}
</span>
),
},
{
title: '实名认证',
dataIndex: 'namecertify',
key: 'namecertify',
render: (text, record) => (
<span>
{record.real_name_auth === "authed" ?
<span className={"pdfdownloadfont00CC5F"}>已认证</span> : record.real_name_auth === "authing" ?
<span className={"pdfdownloadfontFF6602"}>待审核</span> : record.real_name_auth === "not_authed" ?
<span className={"color-red"}>未认证</span> : ""}
),
},
{
title: '实名认证',
dataIndex: 'namecertify',
key: 'namecertify',
render: (text, record) => (
<span>
{record.real_name_auth==="authed"?<span className={"pdfdownloadfont00CC5F"}>已认证</span>:record.real_name_auth==="authing"?<span className={"pdfdownloadfontFF6602"}></span>:record.real_name_auth==="not_authed"?<span className={"color-red"}></span>:""}
</span>
),
},
{
title: '职业认证',
key: 'certify',
dataIndex: 'certify',
render: (text, record) => (
<span>
{record.professional_auth === "authed" ?
<span className={"pdfdownloadfont00CC5F"}>已认证</span> : record.real_name_auth === "authing" ?
<span className={"pdfdownloadfontFF6602"}>待审核</span> : record.real_name_auth === "not_authed" ?
<span className={"color-red"}>未认证</span> : ""}
),
},
{
title: '职业认证',
key: 'certify',
dataIndex: 'certify',
render: (text, record) => (
<span>
{record.professional_auth==="authed"?<span className={"pdfdownloadfont00CC5F"}>已认证</span>:record.real_name_auth==="authing"?<span className={"pdfdownloadfontFF6602"}></span>:record.real_name_auth==="not_authed"?<span className={"color-red"}></span>:""}
</span>
),
},
{
title: '手机绑定',
key: 'mobile',
dataIndex: 'mobile',
render: (text, record) => (
<span>
{record.phone_binded === true ? <span className={"pdfdownloadfont00CC5F"}>已绑定</span> :
<span className={"color-red"}>未绑定</span>}
),
},
{
title: '手机绑定',
key: 'mobile',
dataIndex: 'mobile',
render: (text, record) => (
<span>
{record.phone_binded===true?<span className={"pdfdownloadfont00CC5F"}>已绑定</span>:<span className={"color-red"}></span>}
</span>
),
},
{
title: '邮箱绑定',
key: 'mail',
dataIndex: 'mail',
render: (text, record) => (
<span>
{record.email_binded === true ? <span className={"pdfdownloadfont00CC5F"}>已绑定</span> :
<span className={"color-red"}>未绑定</span>}
),
},
{
title: '邮箱绑定',
key: 'mail',
dataIndex: 'mail',
render: (text, record) => (
<span>
{record.email_binded===true?<span className={"pdfdownloadfont00CC5F"}>已绑定</span>:<span className={"color-red"}></span>}
</span>
),
},
),
},
{
title: '开户行及银行卡号信息(队长填写)',
key: 'idcard',
dataIndex: 'idcard',
render: (value, record, index) => {
if (index === 0 && record.bank_account != null) {
if (index === 0&&record.bank_account!=null) {
return {
children:
<span>{record.bank_account.bank + record.bank_account.second_bank + record.bank_account.card_no}</span>,
children: <span>{record.bank_account.bank + record.bank_account.second_bank + record.bank_account.card_no}</span>,
};
}
},
},
];
];
let people = [{url: '/api/competitions/xxxxx/certificates/1/personal'},
{url: '/api/competitions/xxxxx/certificates/2/personal'},]
let people=[ { url: '/api/competitions/xxxxx/certificates/1/personal' },
{ url: '/api/competitions/xxxxx/certificates/2/personal' },]
return (
<React.Fragment>
<Row>
@ -149,16 +140,13 @@ class CompetitionContentspdfdownload extends Component {
</Row>
<Row className={"mt30"}>
<Col>个人证书 {data && data.personal_certifications.length === 0 ?
<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span
className={"pdfpicture font-14"}>还未认证个人信息</span><a className={"pdfdownloadfont4CACFF"}
onClick={() => this.props.Competitioncallback("2")}>立即查看</a></span></span> :
data && data.personal_certifications.map((item, key) => {
return (
<Col>个人证书{data&&data.personal_certifications.length===0?<span><span className={"pdfpicture font-14"}>暂未生成</span> <span className={"ml20"}><span className={"pdfpicture font-14"}></span><a className={"pdfdownloadfont4CACFF"} onClick={()=>this.props.Competitioncallback("2")}></a></span></span>:
data&&data.personal_certifications.map((item,key)=>{
return(
<span className={"mr10"} key={key}>
<img src={getImageUrl(`images/educoder/pdfs.png`)}/>
<a className={"pdfdownloadfont4CACFF ml10"} href={item.url} download=""
title="下载" mce_href="#">立即下载</a>
<img src={ getImageUrl(`images/educoder/pdfs.png`)} />
<a className={"pdfdownloadfont4CACFF ml10"} href={item.url} download=""
title="下载" mce_href="#">立即下载</a>
</span>
)
})}</Col>
@ -166,19 +154,19 @@ class CompetitionContentspdfdownload extends Component {
<Row className={"mt30"}>
<Col>团队证书
{data && data.team_certifications.length === 0 ? <span className={"pdfpicture font-14"}>暂未生成</span>
: data && data.team_certifications.map((item, key) => {
return (
{data&&data.team_certifications.length===0?<span className={"pdfpicture font-14"}>暂未生成</span>
:data&&data.team_certifications.map((item,key)=>{
return(
<span className={"mr10"} key={key}>
<img src={getImageUrl(`images/educoder/pdfs.png`)}/>
<a className={"pdfdownloadfont4CACFF ml10"} href={item.url} download=""
title="下载" mce_href="#">立即下载</a>
<img src={ getImageUrl(`images/educoder/pdfs.png`)} />
<a className={"pdfdownloadfont4CACFF ml10"} href={item.url} download=""
title="下载" mce_href="#">立即下载</a>
</span>
)
})}
</Col>
</Row>
<Divider/>
<Divider />
<style>
{
`
@ -195,13 +183,12 @@ class CompetitionContentspdfdownload extends Component {
`
}
</style>
{teams && teams.map((item, key) => {
return (
{teams&&teams.map((item,key)=>{
return(
<Row className={"mt30"} key={key}>
<Col className={"pdfpicture mb20"}>{item.name}战队信息填报概况</Col>
<Table columns={columns} dataSource={item.team_members} className={"pdfdownloadTable"}
pagination={false}/>
<Table columns={columns} dataSource={item.team_members} className={"pdfdownloadTable"} pagination={false}/>
</Row>
)
})
@ -212,5 +199,4 @@ class CompetitionContentspdfdownload extends Component {
)
}
}
export default CompetitionContentspdfdownload;
export default CompetitionContentspdfdownload;
Loading…
Cancel
Save