Merge branch 'develop' of https://git.trustie.net/jacknudt/trustieforge into develop

This commit is contained in:
huang 2016-04-14 13:44:14 +08:00
commit fddf03d80c
69 changed files with 2104 additions and 364 deletions

View File

@ -1 +1 @@
{"access_token":"7MBMEBoE6sSC15bIHZYAZSxj47yCKlbWEVjrkUgEJxPP3K083tbhc1RIWmxGu3WoB5dAXxK_yd4l1jrcvt6YrsTcOfFGRirOHVfzrpvhsQgxOoxcdc7YljfO_dnwUtWgFTAcAIALZG","expires_in":7200,"got_token_at":1460189856}
{"access_token":"q51KZUeA6_-CCCH-Buy1mxFmRjcrCViHgk2mHHHqEDbjuA_pgCM1IyW1DASYvpzyB06xHiarujo3rz1Ucq3GRoXdgQ7hAoFCzkL_q3Z5vczLjwAjowAVwmulYE-cAij8ATUfADAWPQ","expires_in":7200,"got_token_at":1460601163}

View File

@ -13,7 +13,7 @@ module Mobile
else
case f
when :img_url
url_to_avatar(u)
"/images/#{url_to_avatar(u)}"
when :gender
u.nil? || u.user_extensions.nil? || u.user_extensions.gender.nil? ? 0 : u.user_extensions.gender
when :work_unit
@ -24,6 +24,8 @@ module Mobile
u.nil? || u.user_extensions.nil? ? "" : u.user_extensions.brief_introduction
when :student_num
u.nil? || u.user_extensions.nil? ? "" : u.user_extensions.student_id
when :realname
u.nil? ? "" : get_user_realname(u)
end
end
end
@ -37,7 +39,7 @@ module Mobile
#昵称
expose :nickname
#真名
expose :realname
user_expose :realname
#性别
user_expose :gender
#我的二维码

View File

@ -557,4 +557,14 @@ class AdminController < ApplicationController
end
end
#代码测试列表
def code_work_tests
@code_work_tests = StudentWorkTest.find_by_sql("select a.* ,b.id as homeworkid,d.language from student_work_tests as a , homework_commons as b ,student_works as c, homework_detail_programings as d where a.student_work_id = c.id and b.id = c.homework_common_id and c.homework_common_id = d.homework_common_id order by a.created_at desc")
#@code_work_tests = StudentWorkTest.order('created_at desc')
@code_work_tests = paginateHelper @code_work_tests,30
@page = (params['page'] || 1).to_i - 1
respond_to do |format|
format.html
end
end
end

View File

@ -883,6 +883,7 @@ class CoursesController < ApplicationController
@course_activities = course_activities.order('updated_at desc').limit(10).offset(@page * 10)
end
@type = params[:type]
respond_to do |format|
format.js
format.html{render :layout => 'base_courses'}
@ -923,6 +924,66 @@ class CoursesController < ApplicationController
end
end
def search_homework_member homeworks,name
if name == ""
select_homework = homeworks
else
name = name.downcase
select_homework = homeworks.select{ |homework|
homework.user[:login].to_s.downcase.include?(name) || homework.user.user_extensions[:student_id].to_s.downcase.include?(name) || (homework.user[:lastname].to_s.downcase + homework.user[:firstname].to_s.downcase).include?(name)
}
end
select_homework
end
# 作业查重
def code_repeat
#代码查重新加的
@order,@b_sort,@name,@group = params[:order] || "score",params[:sort] || "desc",params[:name] || "",params[:group]
@is_teacher = User.current.allowed_to?(:as_teacher,@course) || User.current.admin?
@homework = HomeworkCommon.find params[:homework]
#order("#{@order} #{@b_sort}"
@student_works = search_homework_member @homework.student_works.select("student_works.*,IF(final_score is null,null,IF(final_score = 0, 0, final_score - absence_penalty - late_penalty)) as score").order("simi_value desc"),@name
@works_hash = {}
@student_works.each do |tmpwork|
@works_hash[tmpwork.id] = tmpwork
end
#respond_to do |format|
#format.html {render :layout => 'base_courses'}
#end
end
def show_comparecode
src_id = params[:src_id]
dst_id = params[:dst_id]
src_work = StudentWork.where("id =?", src_id).first
@homework = HomeworkCommon.find params[:homework_id]
@src_code = src_work.description
src_user = User.where("id =?", src_work.user_id).first
@src_username = src_user.try(:realname) != " " ? src_user.lastname + src_user.firstname : src_user.try(:login)
#descriotion user name
dst_work = StudentWork.where("id =?", dst_id).first
@dst_code = dst_work.description
dst_user = User.where("id =?", dst_work.user_id).first
@dst_username = dst_user.try(:realname) != " " ? dst_user.lastname + dst_user.firstname : dst_user.try(:login)
respond_to do |format|
format.js
end
end
#根据已有课程复制课程
#param id:已有课程ID
def copy_course
@ -1077,7 +1138,7 @@ class CoursesController < ApplicationController
sql_select = ""
if groupid == 0
sql_select = "SELECT members.*,(
SELECT SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,student_works.final_score - student_works.absence_penalty - student_works.late_penalty)))
SELECT SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,IF((student_works.final_score - student_works.absence_penalty - student_works.late_penalty) < 0 , 0, student_works.final_score - student_works.absence_penalty - student_works.late_penalty))))
FROM student_works,homework_commons
WHERE student_works.homework_common_id = homework_commons.id
AND homework_commons.course_id = #{@course.id}
@ -1089,7 +1150,7 @@ class CoursesController < ApplicationController
WHERE members.course_id = #{@course.id} ORDER BY score #{score_sort_by}"
else
sql_select = "SELECT members.*,(
SELECT SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,student_works.final_score - student_works.absence_penalty - student_works.late_penalty)))
SELECT SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,IF((student_works.final_score - student_works.absence_penalty - student_works.late_penalty) < 0 , 0, student_works.final_score - student_works.absence_penalty - student_works.late_penalty))))
FROM student_works,homework_commons
WHERE student_works.homework_common_id = homework_commons.id
AND homework_commons.course_id = #{@course.id}

View File

@ -17,9 +17,11 @@ class HomeworkCommonController < ApplicationController
@page = params[:page] ? params[:page].to_i + 1 : 0
@is_teacher = User.current.logged? && (User.current.admin? || User.current.allowed_to?(:as_teacher,@course))
if @is_teacher
@homeworks = @course.homework_commons.order("created_at desc").limit(10).offset(@page * 10)
@homeworks = @course.homework_commons.order("updated_at desc").limit(10).offset(@page * 10)
@homework_commons = @course.homework_commons.order("created_at desc").limit(10).offset(@page * 10)
else
@homeworks = @course.homework_commons.where("publish_time <= '#{Date.today}'").order("created_at desc").limit(10).offset(@page * 10)
@homeworks = @course.homework_commons.where("publish_time <= '#{Date.today}'").order("updated_at desc").limit(10).offset(@page * 10)
@homework_commons = @course.homework_commons.where("publish_time <= '#{Date.today}'").order("created_at desc").limit(10).offset(@page * 10)
end
@is_student = User.current.logged? && (User.current.admin? || (User.current.member_of_course?(@course) && !@is_teacher))
@is_new = params[:is_new]

View File

@ -352,8 +352,13 @@ class OrganizationsController < ApplicationController
if !params[:name].nil?
condition = "%#{params[:name].strip}%".gsub(" ","")
end
sql = "select courses.* from courses inner join members on courses.id = members.course_id where members.user_id = #{User.current.id} and courses.is_public = 1 and courses.name like '#{condition}'"+
"and courses.id not in (select distinct org_courses.course_id from org_courses where org_courses.organization_id = #{@organization.id}) and courses.is_delete=0"
if User.current.admin?
sql = "select courses.* from courses where courses.is_public = 1 and courses.name like '#{condition}'"+
"and courses.id not in (select distinct org_courses.course_id from org_courses where org_courses.organization_id = #{@organization.id}) and courses.is_delete=0"
else
sql = "select courses.* from courses inner join members on courses.id = members.course_id where members.user_id = #{User.current.id} and courses.is_public = 1 and courses.name like '#{condition}'"+
"and courses.id not in (select distinct org_courses.course_id from org_courses where org_courses.organization_id = #{@organization.id}) and courses.is_delete=0"
end
#user_courses = Course.find_by_sql(sql)
@courses = Course.find_by_sql(sql)
# @added_course_ids = @organization.courses.map(&:id)
@ -396,8 +401,13 @@ class OrganizationsController < ApplicationController
if !params[:name].nil?
condition = "%#{params[:name].strip}%".gsub(" ","")
end
sql = "select projects.* from projects inner join members on projects.id = members.project_id where members.user_id = #{User.current.id} and projects.status != 9 and projects.is_public = 1 and projects.name like '#{condition}'" +
if User.current.admin?
sql = "select projects.* from projects where projects.status != 9 and projects.is_public = 1 and projects.name like '#{condition}'" +
" and projects.id not in (select org_projects.project_id from org_projects where organization_id = #{@organization.id}) and status=1"
else
sql = "select projects.* from projects inner join members on projects.id = members.project_id where members.user_id = #{User.current.id} and projects.status != 9 and projects.is_public = 1 and projects.name like '#{condition}'" +
" and projects.id not in (select org_projects.project_id from org_projects where organization_id = #{@organization.id}) and status=1"
end
#user_projects = Course.find_by_sql(sql)
@projects = Course.find_by_sql(sql)
# @added_course_ids = @organization.projects.map(&:id)

View File

@ -5,7 +5,7 @@ class StudentWorkController < ApplicationController
include ApplicationHelper
require 'bigdecimal'
require "base64"
before_filter :find_homework, :only => [:new, :index, :create, :student_work_absence_penalty, :absence_penalty_list, :evaluation_list, :program_test,:program_test_ex,:set_score_rule,:forbidden_anonymous_comment,:delete_work,:new_student_work_project,:student_work_project,:cancel_relate_project,:search_course_students]
before_filter :find_homework, :only => [:new, :index, :create, :student_work_absence_penalty, :absence_penalty_list, :evaluation_list, :program_test,:program_test_ex,:code_repeattest,:set_score_rule,:forbidden_anonymous_comment,:delete_work,:new_student_work_project,:student_work_project,:cancel_relate_project,:search_course_students]
before_filter :find_work, :only => [:edit, :update, :show, :destroy, :add_score, :praise_student_work,:retry_work,:revise_attachment]
before_filter :member_of_course, :only => [:new, :create, :show, :add_score, :praise_student_work]
before_filter :author_of_work, :only => [:edit, :update, :destroy]
@ -81,6 +81,8 @@ class StudentWorkController < ApplicationController
#根据传入的tIndex确定是第几次测试
#之后如果觉得很卡 可以改成将结果传回JS再以参数形式传回来
def program_test_ex
tStarttime = Time.now
is_test = params[:is_test] == 'true'
resultObj = {status: 0, results: [], error_msg: '', time: Time.now.strftime('%Y-%m-%d %T'),tseq:1,tcount:1,testid:1} #保存每测试一次返回的结果
@ -134,6 +136,16 @@ class StudentWorkController < ApplicationController
end
#每次从数据库取出上次的结果加上本次的结果再存入数据库
tEndtime = Time.now
tUsedtime = (tEndtime.to_i-tStarttime.to_i)*1000+(tEndtime.usec - tStarttime.usec)/1000
if result["status"].to_i != -2
result["results"].first['user_wait'] = tUsedtime
end
if result["results"][0]["status"].to_i == 2
result["status"] = 2
end
status = result["status"]
if index == 1
student_work_test = student_work.student_work_tests.build(status: status,
@ -162,6 +174,11 @@ class StudentWorkController < ApplicationController
resultObj[:index] = student_work.student_work_tests.count
end
tEndtime = Time.now
tUsedtime = (tEndtime.to_i-tStarttime.to_i)*1000+(tEndtime.usec - tStarttime.usec)/1000
logger.debug "program_test_ex user wait time = #{tUsedtime} 毫秒"
#渲染返回结果
render :json => resultObj
end
@ -169,6 +186,106 @@ class StudentWorkController < ApplicationController
end
end
#找出该作业的所有提交作业
def find_all_student_work_by_homeid()
all_studentwork = StudentWork.where("homework_common_id =?", @homework.id)
all_studentwork
end
def request_code_repeattest(src)
url = "#{Redmine::Configuration['jplag_server']}api/realtime_test.json"
factor = []
src.each do |test|
factor << {work_id: test.id, des: test.description,created_at:test.created_at.to_i}
end
solutions = {
homeid:@homework.id,
language:@homework.homework_detail_programing.language,
factor: factor
}
uri = URI(url)
body = solutions.to_json
logger.debug "send body"
logger.debug body
res = Net::HTTP.new(uri.host, uri.port).start do |client|
request = Net::HTTP::Post.new(uri.path)
request.body = body
request["Content-Type"] = "application/json"
client.request(request)
end
JSON.parse(res.body)
end
#代码查重 status: 0完成 -2不需要查重 -1查重失败不支持该语言
def code_repeattest
tStarttime = Time.now
logger.debug "code_repeattest start is #{tStarttime}}"
resultObj = {status: -2}
@homework = HomeworkCommon.find params[:homework]
all_studentwork = find_all_student_work_by_homeid()
if all_studentwork == nil
resultObj[:status] = -2
elsif all_studentwork.count <= 1
resultObj[:status] = -2
else
#@homework.homework_detail_programing.language、id、description
logger.debug "time1 is #{Time.now.usec} "
result = request_code_repeattest(all_studentwork)
logger.debug "time2 is #{Time.now.usec} "
resultObj[:status] = result['status'].to_i
# resultObj[:results] = result['results']
#Time.now, simi_id = simiworkid , simi_value = simivalue
if resultObj[:status] == 0
@homework.simi_time = Time.now
resultObj[:comparetime] = @homework.simi_time
@homework.update_column('simi_time', @homework.simi_time)
logger.debug "time3 is #{Time.now.usec} "
result['results'].each do |key,value|
if value['simiworkid'].to_i > 0
@student_work = StudentWork.where("id =?", key.to_i).first
@student_work.update_column('simi_id', value['simiworkid'].to_i)
@student_work.update_column('simi_value', value['simivalue'].to_i)
end
# sqlstr = "update student_works set simi_id=#{value['simiworkid']},simi_value=#{value['simivalue']} where id=#{key.to_i} "
# dbh.execute(sqlstr)
end
logger.debug "time4 is #{Time.now.usec} "
end
end
tEndtime = Time.now
logger.debug "code_repeattest end is #{tEndtime}}"
tUsedtime = (tEndtime.to_i-tStarttime.to_i)*1000000+(tEndtime.usec - tStarttime.usec)
logger.debug "code_repeattest userd utime is #{tUsedtime}"
render :json => resultObj
end
def last_codecomparetime
resultObj = {status: 0}
@homework = HomeworkCommon.find params[:homework]
#转换一下
if @homework.simi_time != nil
resultObj[:comparetime] = Time.parse(@homework.simi_time.to_s).strftime("%Y-%m-%d %H:%M")
else
resultObj[:comparetime] = @homework.simi_time
end
render :json => resultObj
end
def index
# 作业消息状态更新
@ -351,6 +468,7 @@ class StudentWorkController < ApplicationController
render_403
return
end
@student_work_count = (search_homework_member @homework.student_works.select("student_works.*,IF(final_score is null,null,IF(final_score = 0, 0, final_score - absence_penalty - late_penalty)) as score").order("#{@order} #{@b_sort}"),@name).count
end
@ -1152,6 +1270,7 @@ class StudentWorkController < ApplicationController
request["Content-Type"] = "application/json"
client.request(request)
end
JSON.parse(res.body)
end

View File

@ -1122,13 +1122,13 @@ class UsersController < ApplicationController
#显示更多用户课程
def user_courses4show
@page = params[:page].to_i + 1
@courses = @user.courses.visible.where("is_delete =?", 0).select("courses.*,(SELECT MAX(created_at) FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a").order("a desc").limit(5).offset(@page * 5)
@courses = @user.courses.visible.where("is_delete =?", 0).select("courses.*,(SELECT MAX(updated_at) FROM `course_activities` WHERE course_activities.course_id = courses.id) AS a").order("a desc").limit(5).offset(@page * 5)
end
#显示更多用户项目
def user_projects4show
@page = params[:page].to_i + 1
@projects = @user.projects.visible.select("projects.*,(SELECT MAX(created_at) FROM `forge_activities` WHERE forge_activities.project_id = projects.id) AS a").order("a desc").limit(5).offset(@page * 5)
@projects = @user.projects.visible.select("projects.*,(SELECT MAX(updated_at) FROM `forge_activities` WHERE forge_activities.project_id = projects.id) AS a").order("a desc").limit(5).offset(@page * 5)
end
def user_course_activities

View File

@ -143,7 +143,7 @@ class WechatsController < ActionController::Base
url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{login_wechat_url}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"
article.item title: "#{n[:title]}",
description: n[:content],
pic_url: 'http://wechat.trustie.net/images/trustie_logo2.png',
pic_url: 'https://www.trustie.net/images/trustie_logo2.png',
url: url
end
end

View File

@ -27,6 +27,10 @@ module ApiHelper
location
end
def get_user_realname user
name = user.lastname + user.firstname
name.empty? || name.nil? || name == " " ? user.login : name
end
def get_assigned_homeworks(homeworks, n, index)
homeworks += homeworks

View File

@ -850,7 +850,7 @@ module CoursesHelper
# 学生按作业总分排序取前8个
def hero_homework_score(course, score_sort_by)
sql_select = "SELECT members.*,(
SELECT SUM(IF(student_works.final_score is null,null,IF(student_works.final_score = 0, 0, student_works.final_score - student_works.absence_penalty - student_works.late_penalty)))
SELECT SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,IF((student_works.final_score - student_works.absence_penalty - student_works.late_penalty) < 0 , 0, student_works.final_score - student_works.absence_penalty - student_works.late_penalty))))
FROM student_works,homework_commons
WHERE student_works.homework_common_id = homework_commons.id
AND homework_commons.course_id = #{course.id}

View File

@ -78,48 +78,13 @@ class BlogComment < ActiveRecord::Base
#博客回复微信模板消息
def blog_wechat_message
# 发布博客
unless self.parent_id.nil?
uw = UserWechat.where(user_id: self.parent.author_id).first
#unless uw.nil? && self.parent.author_id != User.current.id
unless uw.nil?
data = {
touser:uw.openid,
template_id:"A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c",
url:"http://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:"您的博客有新回复了",
color:"#173177"
},
keyword1:{
value:self.author.try(:realname),
color:"#173177"
},
keyword2:{
value:format_time(self.created_at),
color:"#173177"
},
keyword3:{
value:self.content.html_safe,
color:"#173177"
},
remark:{
value:"具体内容请点击详情查看网站",
color:"#173177"
}
}
}
logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
logger.error "[blog_comment] ===> #{e}"
end
logger.info "send over. #{req}"
ws = WechatService.new
if self.parent_id.nil?
self.author.watcher_users.each do |watcher|
ws.message_update_template watcher.id, "#{l(:label_new_blog_template)}", self.author.try(:realname) + " 发表了博客:" + self.title.html_safe, format_time(self.created_at)
end
else
ws.comment_template self.parent.author_id, "#{l(:label_blog_comment_template)}", self.author.try(:realname), format_time(self.created_at), self.content.html_safe
end
end
end

View File

@ -16,6 +16,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Comment < ActiveRecord::Base
require 'net/http'
require 'json'
include Redmine::SafeAttributes
include ApplicationHelper
has_many_kindeditor_assets :assets, :dependent => :destroy
@ -39,13 +41,16 @@ class Comment < ActiveRecord::Base
after_destroy :down_course_score
def act_as_system_message
ws = WechatService.new
if self.commented.course
if self.author_id != self.commented.author_id
self.course_messages << CourseMessage.new(:user_id => self.commented.author_id, :course_id => self.commented.course.id, :viewed => false)
ws.comment_template self.commented.author_id, "#{l(:label_notice_comment_template)}", self.author.try(:realname), format_time(self.created_on), self.comments.html_safe
end
else # 项目相关
if self.author_id != self.commented.author_id
self.forge_messages << ForgeMessage.new(:user_id => self.commented.author_id, :project_id => self.commented.project.id, :viewed => false)
ws.comment_template self.commented.author_id, "#{l(:label_news_comment_template)}", self.author.try(:realname), format_time(self.created_on), self.comments.html_safe
end
end
end

View File

@ -2,7 +2,7 @@
#老师布置的作业表
#homework_type: 0:普通作业;1:匿评作业;2:编程作业
class HomeworkCommon < ActiveRecord::Base
# attr_accessible :name, :user_id, :description, :publish_time, :end_time, :homework_type, :late_penalty, :course_id
# attr_accessible :name, :user_id, :description, :publish_time, :end_time, :homework_type, :late_penalty, :course_id,:simi_time
require 'net/http'
require 'json'
include Redmine::SafeAttributes
@ -59,6 +59,8 @@ class HomeworkCommon < ActiveRecord::Base
self.course.members.each do |m|
# if m.user_id != self.user_id
self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.course_id, :viewed => false)
ws = WechatService.new
ws.homework_template(m.user_id, "#{l(:label_new_homework_template)}", self.course.name, self.name.html_safe, self.end_time.to_s + " 23:59:59")
# end
end
end
@ -104,44 +106,8 @@ class HomeworkCommon < ActiveRecord::Base
#修改作业后发送微信模板消息
def wechat_message
self.course.members.each do |member|
uw = UserWechat.where("user_id=?", member.user_id).first
unless uw.nil?
data = {
touser:uw.openid,
template_id:"3e5Dj2GIx8MOcMyRKpTUEQnM7Tg0ASSCNc01NS9HCGI",
url:"http://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:"您的作业已被修改",
color:"#173177"
},
keyword1:{
value:self.course.name,
color:"#173177"
},
keyword2:{
value:self.name,
color:"#173177"
},
keyword3:{
value:self.end_time.to_s + "23:59:59",
color:"#173177"
},
remark:{
value:"具体内容请点击详情查看网站",
color:"#173177"
}
}
}
logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
logger.error "[homework_common] ===> #{e}"
end
logger.info "send over. #{req}"
end
ws = WechatService.new
ws.homework_template(member.user_id, "#{l(:label_update_homework_template)}", self.course.name, self.name.html_safe, self.end_time.to_s + " 23:59:59")
end
end

View File

@ -1,3 +1,4 @@
#encoding: utf-8
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
@ -16,6 +17,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Issue < ActiveRecord::Base
require 'net/http'
require 'json'
include Redmine::SafeAttributes
include Redmine::Utils::DateCalculation
include UserScoreHelper
@ -156,6 +159,8 @@ class Issue < ActiveRecord::Base
# 指派给自己的缺陷不提示消息
unless self.author_id == self.assigned_to_id
self.forge_messages << ForgeMessage.new(:user_id => self.assigned_to_id, :project_id => self.project_id, :viewed => false)
ws = WechatService.new
ws.message_update_template self.assigned_to_id, "#{l(:label_new_issue_template)}", self.author.try(:realname) + " 给您指派了缺陷:" + self.subject.html_safe, format_time(self.created_on)
end
if self.tracker_id == 5
self.project.members.each do |m|

View File

@ -239,44 +239,7 @@ class Journal < ActiveRecord::Base
#缺陷回复微信模板消息
def issue_wechat_message
uw = UserWechat.where(user_id: self.issue.author_id).first
#unless uw.nil? && self.issue.author_id != User.current.id
unless uw.nil?
data = {
touser:uw.openid,
template_id:"A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c",
url:"http://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:"您的缺陷有新回复了",
color:"#173177"
},
keyword1:{
value:self.user.try(:realname),
color:"#173177"
},
keyword2:{
value:format_time(self.created_on),
color:"#173177"
},
keyword3:{
value:self.notes.html_safe,
color:"#173177"
},
remark:{
value:"具体内容请点击详情查看网站",
color:"#173177"
}
}
}
logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
logger.error "[journal] ===> #{e}"
end
logger.info "send over. #{req}"
end
ws = WechatService.new
ws.comment_template self.issue.author_id, "#{l(:label_issue_comment_template)}", self.user.try(:realname), format_time(self.created_on), self.notes.html_safe
end
end

View File

@ -256,7 +256,8 @@ class JournalsForMessage < ActiveRecord::Base
end
end
if self.jour_type == 'HomeworkCommon'
journal_wechat_message '您的作业有新回复了',self.jour.user_id
ws = WechatService.new
ws.comment_template self.jour.user_id, "#{l(:label_homework_comment_template)}", self.user.try(:realname), format_time(self.created_on), self.notes.html_safe
end
end
@ -264,12 +265,13 @@ class JournalsForMessage < ActiveRecord::Base
# 用户留言消息通知
def act_as_user_feedback_message
# 主留言
ws = WechatService.new
if self.jour_type == 'Principal'
receivers = []
if self.reply_id == 0
if self.user_id != self.jour_id # 过滤自己给自己的留言消息
receivers << self.jour
journal_wechat_message "您有新留言了",self.jour_id
ws.message_update_template self.jour_id, "#{l(:label_new_journals_template)}", self.notes.html_safe, format_time(self.created_on)
end
else # 留言回复
reply_to = User.find(self.reply_id)
@ -279,12 +281,11 @@ class JournalsForMessage < ActiveRecord::Base
if self.user_id != self.parent.jour_id && self.reply_id != self.parent.jour_id # 给东家发信息,如果回复的对象是东家则不发
receivers << self.parent.jour
end
journal_wechat_message "您的留言有新回复了",self.reply_id
ws.comment_template self.reply_id, "#{l(:label_journals_comment_template)}", self.user.try(:realname), format_time(self.created_on), self.notes.html_safe
end
receivers.each do |r|
self.user_feedback_messages << UserFeedbackMessage.new(:user_id => r.id, :journals_for_message_id => self.id, :journals_for_message_type => "Principal", :viewed => false)
end
end
end
@ -305,48 +306,4 @@ class JournalsForMessage < ActiveRecord::Base
down_course_score_num(self.jour.course_id, self.user_id, "HomeworkCommon")
end
end
#微信模板消息
def journal_wechat_message type, user_id
uw = UserWechat.where(user_id: user_id).first
#unless uw.nil? && self.reply_id != User.current.id
unless uw.nil?
data = {
touser:uw.openid,
template_id:"A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c",
url:"http://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:type,
color:"#173177"
},
keyword1:{
value:self.user.try(:realname),
color:"#173177"
},
keyword2:{
value:format_time(self.created_on),
color:"#173177"
},
keyword3:{
value:self.notes.html_safe,
color:"#173177"
},
remark:{
value:"具体内容请点击详情查看网站",
color:"#173177"
}
}
}
logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
logger.error "[journal_for_message] ===> #{e}"
end
logger.info "send over. #{req}"
end
end
end

View File

@ -17,8 +17,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Mailer < ActionMailer::Base
require 'net/http'
require 'json'
layout 'mailer'
helper :application
helper :issues
@ -642,9 +640,6 @@ class Mailer < ActionMailer::Base
mail :to => recipients,
:subject => "[ #{l(:label_user_homework)} : #{homework_common.name} #{l(:label_memo_create_succ)}]",
:filter => true
@homework_common.course.members.each do |member|
mail_wechat_message member.user_id, "3e5Dj2GIx8MOcMyRKpTUEQnM7Tg0ASSCNc01NS9HCGI", "您的课程有新作业了", @homework_common.course.name, @homework_common.name, @homework_common.end_time.to_s + " 23:59:59"
end
end
# Builds a Mail::Message object used to email recipients of a news' project when a news item is added.
@ -710,8 +705,6 @@ class Mailer < ActionMailer::Base
mail :to => recipients,
:subject => "[#{news.course.name}] #{l(:label_news)}: #{news.title}",
:filter => true
mail_wechat_message news.author_id, "A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c", "您的课程通知有新回复了", @author.try(:realname), format_time(comment.created_on), comment.comments.html_safe
end
end
@ -736,14 +729,7 @@ class Mailer < ActionMailer::Base
:cc => cc,
:subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}",
:filter => true
if message.parent_id == nil
message.project.members.each do |member|
mail_wechat_message member.user_id, "oKzFCdk7bsIHnGbscA__N8LPQrBkUShvpjV3-kuwWDQ", "项目讨论区有新帖子发布了", message.subject, @author.try(:realname), format_time(message.created_on)
end
else
mail_wechat_message message.parent.author_id, "A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c", "您的帖子有新回复了", @author.try(:realname), format_time(message.created_on), message.content.html_safe
end
elsif message.course
elsif message.course
redmine_headers 'Course' => message.course.id,
'Topic-Id' => (message.parent_id || message.id)
@author = message.author
@ -758,14 +744,7 @@ class Mailer < ActionMailer::Base
:cc => cc,
:subject => "[#{message.board.course.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}",
:filter => true
if message.parent_id == nil
message.course.members.each do |member|
mail_wechat_message member.user_id, "oKzFCdk7bsIHnGbscA__N8LPQrBkUShvpjV3-kuwWDQ", "课程问答区有新帖子发布了", message.subject, @author.try(:realname), format_time(message.created_on)
end
else
mail_wechat_message message.parent.author_id, "A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c", "您的帖子有新回复了", @author.try(:realname), format_time(message.created_on), message.content.html_safe
end
end
end
# Builds a Mail::Message object used to email the recipients of a project of the specified wiki content was added.
@ -1119,48 +1098,4 @@ class Mailer < ActionMailer::Base
1.upto(len) { |i| newpass << chars[rand(chars.size-1)] }
return newpass
end
#微信模板消息
def mail_wechat_message user_id, template_id, first, key1, key2, key3, remark="具体内容请点击详情查看网站"
uw = UserWechat.where(user_id: user_id).first
logger.info "mail_wechat_message #{user_id} #{uw}"
unless uw.nil?
data = {
touser:uw.openid,
template_id:template_id,
url:"http://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:first,
color:"#173177"
},
keyword1:{
value:key1,
color:"#173177"
},
keyword2:{
value:key2,
color:"#173177"
},
keyword3:{
value:key3,
color:"#173177"
},
remark:{
value:remark,
color:"#173177"
}
}
}
logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
logger.error "[mailer] ===> #{e}"
end
logger.info "send over. #{req}"
end
end
end

View File

@ -158,7 +158,7 @@ class Member < ActiveRecord::Base
end
def student_work_score_sum
sql_select = "SELECT (SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,student_works.final_score - student_works.absence_penalty - student_works.late_penalty)))) as score
sql_select = "SELECT (SUM(IF(student_works.final_score IS NULL,NULL,IF(student_works.final_score =0,0,IF((student_works.final_score - student_works.absence_penalty - student_works.late_penalty) < 0 , 0, student_works.final_score - student_works.absence_penalty - student_works.late_penalty))))) AS score
FROM student_works,homework_commons
WHERE student_works.homework_common_id = homework_commons.id
AND homework_commons.course_id = #{self.course_id}

View File

@ -1,3 +1,4 @@
#encoding: utf-8
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
@ -16,6 +17,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Message < ActiveRecord::Base
require 'net/http'
require 'json'
include Redmine::SafeAttributes
include UserScoreHelper
include ApplicationHelper
@ -257,17 +260,20 @@ class Message < ActiveRecord::Base
# 主贴项目成员都能收到
# 回帖:帖子的发布人收到
def act_as_system_message
ws = WechatService.new
if self.course
if self.parent_id.nil? # 主贴
self.course.members.each do |m|
if self.author.allowed_to?(:as_teacher, self.course) && m.user_id != self.author_id # 老师 自己的帖子不给自己发送消息
self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.board.course_id, :viewed => false)
ws.topic_publish_template m.user_id, "#{l(:label_course_topic_template)}", self.subject, self.author.try(:realname), format_time(self.created_on)
end
end
else # 回帖
self.course.members.each do |m|
if m.user_id == Message.find(self.parent_id).author_id && m.user_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息
self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.board.course_id, :viewed => false)
ws.comment_template m.user_id, "#{l(:label_topic_comment_template)}", self.author.try(:realname), format_time(self.created_on), self.content.html_safe
end
end
end
@ -276,12 +282,14 @@ class Message < ActiveRecord::Base
self.project.members.each do |m|
if m.user_id != self.author_id
self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false)
ws.topic_publish_template m.user_id, "#{l(:label_project_topic_template)}", self.subject, self.author.try(:realname), format_time(self.created_on)
end
end
else # 回帖
self.project.members.each do |m|
if m.user_id == Message.find(self.parent_id).author_id && m.user_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息
self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false)
ws.comment_template m.user_id, "#{l(:label_topic_comment_template)}", self.author.try(:realname), format_time(self.created_on), self.content.html_safe
end
end
end

View File

@ -1,3 +1,4 @@
#encoding: utf-8
# Redmine - project management software
# Copyright (C) 2006-2013 Jean-Philippe Lang
#
@ -16,6 +17,8 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class News < ActiveRecord::Base
require 'net/http'
require 'json'
include Redmine::SafeAttributes
belongs_to :project,:touch => true
include ApplicationHelper
@ -167,6 +170,8 @@ class News < ActiveRecord::Base
self.course.members.each do |m|
if m.user_id != self.author_id
self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.course_id, :viewed => false)
ws = WechatService.new
ws.message_update_template m.user_id, "#{l(:label_new_notice_template)}", self.author.try(:realname) + " 发布了通知:" + self.title.html_safe, format_time(self.created_on)
end
end
else

View File

@ -1,6 +1,6 @@
#学生提交作品表
class StudentWork < ActiveRecord::Base
attr_accessible :name, :description, :homework_common_id, :user_id, :final_score, :teacher_score, :student_score, :teaching_asistant_score, :project_id, :is_test
attr_accessible :name, :description, :homework_common_id, :user_id, :final_score, :teacher_score, :student_score, :teaching_asistant_score, :project_id, :is_test, :simi_id, :simi_value
belongs_to :homework_common
belongs_to :user

View File

@ -0,0 +1,114 @@
#encoding: utf-8
class WechatService
def template_data(openid, template_id, first, key1, key2, key3, remark="具体内容请点击详情查看网站")
data = {
touser:openid,
template_id:template_id,
url:"https://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:first,
color:"#173177"
},
keyword1:{
value:key1,
color:"#173177"
},
keyword2:{
value:key2,
color:"#173177"
},
keyword3:{
value:key3,
color:"#173177"
},
remark:{
value:remark,
color:"#173177"
}
}
}
data
end
def homework_template(user_id, first, key1, key2, key3, remark="具体内容请点击详情查看网站")
uw = UserWechat.where(user_id: user_id).first
unless uw.nil?
data = template_data uw.openid,"3e5Dj2GIx8MOcMyRKpTUEQnM7Tg0ASSCNc01NS9HCGI",first, key1, key2, key3, remark
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
Rails.logger.error "[homework] ===> #{e}"
end
Rails.logger.info "send over. #{req}"
end
end
def topic_publish_template(user_id, first, key1, key2, key3, remark="具体内容请点击详情查看网站")
uw = UserWechat.where(user_id: user_id).first
unless uw.nil?
data = template_data uw.openid,"oKzFCdk7bsIHnGbscA__N8LPQrBkUShvpjV3-kuwWDQ",first, key1, key2, key3, remark
Rails.logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
Rails.logger.error "[topic_publish] ===> #{e}"
end
Rails.logger.info "send over. #{req}"
end
end
def comment_template(user_id, first, key1, key2, key3, remark="具体内容请点击详情查看网站")
uw = UserWechat.where(user_id: user_id).first
unless uw.nil?
data = template_data uw.openid,"A_3f5v90-zK73V9Kijm-paDkl9S-NuM8Cf-1UJi92_c",first, key1, key2, key3, remark
Rails.logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
Rails.logger.error "[comment] ===> #{e}"
end
Rails.logger.info "send over. #{req}"
end
end
def message_update_template(user_id, first, key1, key2, remark="具体内容请点击详情查看网站")
uw = UserWechat.where(user_id: user_id).first
unless uw.nil?
data = {
touser:uw.openid,
template_id:"YTyNPZnQD8uZFBFq-Q6cCOWaq5LA9vL6RFlF2JuD5Cg",
url:"https://www.trustie.net/",
topcolor:"#FF0000",
data:{
first: {
value:first,
color:"#173177"
},
keyword1:{
value:key1,
color:"#173177"
},
keyword2:{
value:key2,
color:"#173177"
},
remark:{
value:remark,
color:"#173177"
}
}
}
Rails.logger.info "start send template message: #{data}"
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
Rails.logger.error "[message_update] ===> #{e}"
end
Rails.logger.info "send over. #{req}"
end
end
end

View File

@ -0,0 +1,96 @@
<h3>
<%=l(:label_code_work_tests)%>
</h3>
&nbsp;
<div class="autoscroll">
<table class="list" style="width: 100%;table-layout: fixed">
<thead>
<tr>
<th style="width: 50px;">
作业id
</th>
<th style="width: 60px;">
平均等待时间
</th>
<th style="width: 50px;">
语言
</th>
<th style="width: 120px;">
提交测试时间
</th>
<th style="width: 50px;">
答题状态
</th>
<th style="width: 50px;">
测试集数
</th>
<th style="width: 50px;">
最小耗时
</th>
<th style="width: 50px;">
最大耗时
</th>
</tr>
</thead>
<tbody>
<% @code_work_tests.each do |test| %>
<tr class="<%= cycle("odd", "even") %>">
<td style="text-align: center; " title='<%=test.homeworkid%>'>
<%=link_to(test.homeworkid, student_work_index_path(:homework => test.homeworkid))%>
</td>
<td style="text-align: center;">
<% if test.status != -2 && test.results.first['user_wait'] %>
<% wait_time = 0 %>
<% test.results.each do |result| wait_time = wait_time + result['user_wait'] end %>
<%=(wait_time/test.results.count).to_s+"毫秒" %>
<% else %>
<%="未记录"%>
<% end %>
</td>
<td align="center">
<%=%W(C C++ Python Java).at(test.language.to_i - 1)%>
</td>
<td align="center">
<%=Time.parse(test.created_at.to_s).strftime("%Y-%m-%d %H:%M:%S")%>
</td>
<td align="center">
<% if test.status == 0 %>
<%= "答题正确" %>
<% elsif test.status == -2 %>
<%= "编译错误" %>
<% elsif test.status == 2 || test.results.last['status'] == 2 %>
<%= "超时" %>
<% else %>
<%= "答题错误" %>
<% end %>
</td>
<td class="center">
<% if test.status != -2 %>
<%=test.results.count%>
<% end %>
</td>
<td class="center">
<% if test.status != -2 %>
<%test.results = test.results.sort_by {|result| result['time_used'] }%>
<%=test.results.first['time_used'] == 0 ? "1毫秒":test.results.first['time_used'].to_s+"毫秒"%>
<% end %>
</td>
<td class="center">
<% if test.status != -2 %>
<%=test.results.last['time_used'] == 0 ? "1毫秒":test.results.last['time_used'].to_s+"毫秒"%>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div class="pagination">
<%= pagination_links_full @obj_pages, @obj_count, :per_page_links => false %>
</div>
<% html_title(l(:label_code_work_tests)) -%>

View File

@ -0,0 +1,101 @@
<div class="blue-border-box">
<div class="box-con">
<%if @homework.simi_time != nil %>
<h4 id = "compare-tips-1"><%="您上次查重的时间为"+Time.parse(@homework.simi_time.to_s).strftime("%Y-%m-%d %H:%M")%></h4>
<%end%>
<div class="box-con-a">
<a href="javascript:void(0);" class="Blue-btn fl " onclick = "compare_code_btn(<%=homework.id%>,<%=courseid%>)">重新查重</a>
<a href="javascript:void(0);" class="Blue-btn fl " onclick = "see_last_compare_code(<%=courseid%>,<%=homework.id%>)">查看结果</a>
</div>
<div class="cl"></div>
</div>
</div>
</div>
<script type="text/javascript">
//请求重新查重
function compare_code_btn(homeworkid,courseid)
{
hideModal($(".blue-border-box"));
test_repeat(homeworkid,courseid);
}
//查看结果
function see_last_compare_code(courseid,homeworkid)
{
hideModal($(".blue-border-box"));
var rootpath = getRootPath();
var code_repeatpath = rootpath+"/courses/"+courseid+"/code_repeat?homework="+homeworkid;
//新打开页面
window.open(code_repeatpath);
}
var test_repeat = function(homeworkid,courseid){
$.post(
'/student_work/code_repeattest',
{homework: homeworkid},
function(data,status){
console.log("result = ");
console.log(data);
if (data.status == 0) {
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"查重完成是否立即查看结果?",:status=>1, :homework=> homework,:courseid=> courseid})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
}
else if (data.status == -1){
// confirm("对不起只支持java/c/c++的代码查重!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起目前只支持java/c/c++的代码查重!",:status=>0, :homework=> homework,:courseid=> courseid})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
}
else if (data.status == -2){
// confirm("对不起该作业的作品过少不能查重!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起该作业的作品过少不能查重!",:status=>0, :homework=> homework,:courseid=> courseid})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
}
return;
}
).fail(function(xhr, status){
// confirm("对不起,服务器繁忙请稍后再试!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起,服务器繁忙请稍后再试!",:status=>0, :homework=> homework,:courseid=> courseid})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
return;
});
};
</script>

View File

@ -0,0 +1,22 @@
<div class="blue-border-box">
<div class="box-con">
<h4><%=des%></h4>
<div class="box-con-a">
<a href="javascript:void(0);" class="Blue-btn " style="width:67px; margin:25px auto 0px auto;" onclick = "yes_btn(<%=status%>,<%=courseid%>,<%=homework.id%>)">确定</a>
</div>
<div class="cl"></div>
</div>
</div>
</div>
<script type="text/javascript">
function yes_btn(status,courseid,homeworkid)
{
hideModal($(".blue-border-box"));
if(status == 1) {
var rootpath = getRootPath();
var code_repeatpath = rootpath+"/courses/"+courseid+"/code_repeat?homework="+homeworkid;
window.open(code_repeatpath);
}
}
</script>

View File

@ -0,0 +1,16 @@
<% content_for :header_tags do %>
<%= javascript_include_tag "/assets/codemirror/codemirror_python_ruby_c" %>
<%= stylesheet_link_tag "/assets/codemirror/codemirror" %>
<%= stylesheet_link_tag "/assets/codemirror/merge" %>
<%= javascript_include_tag "https://cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"%>
<%= javascript_include_tag "/assets/codemirror/merge" %>
<% end %>
<article>
<h3 style="float:left; width:50%; text-align:center;"><%=src_name%></h3>
<h3 style="float:left; width:50%; text-align:center;"><%=dst_name%></h3><div class="cl"></div>
<pre id = "program-src_1" style = "display: none" ><%= src_code if src_code%></pre>
<pre id = "program-src_2" style = "display: none" ><%= dst_code if dst_code%></pre>
<div class = "program-compare-code" id=program-compare-code></div>
</article>

View File

@ -24,7 +24,7 @@
</span>
<span class="c_red w70">
<% final_score = @member_score.homework_common_score(homework_common).first%>
<%= final_score.nil? || final_score.final_score.nil? ? "--" : format("%0.2f", final_score.final_score) %>
<%= final_score.nil? || final_score.final_score.nil? ? "--" : format("%0.2f", final_score.final_score < 0 ? 0 : final_score.final_score) %>
</span>
</li>
<% end %>

View File

@ -0,0 +1,79 @@
<div class="conbox">
<h2 class="conbox-h2">查重结果</h2>
<div class="chabox">
<ul class="chabox-header">
<li class="chabox-w-500" style = "width:413px" >全部作品</li>
<li class="chabox-w-500" style = "width:585px" >对比作品</li>
<div class="cl"></div>
</ul>
<ul class="chabox-top">
<li class="chabox-w-151" >作品名称</li>
<li>姓名</li>
<li>学号 </li>
<li class="chabox-r-line">时间 </li>
<li class="chabox-w-151">作品名称</li>
<li>姓名</li>
<li>学号 </li>
<li class="chabox-r-line">时间 </li>
<li >相似度 </li>
<li >对比 </li>
</ul>
<%if @homework.homework_type == 2 %>
<% @student_works.each do |student_work|%>
<ul class="chabox-con" id = "chabox-con-<%=student_work.id%>" >
<% student_work_name = student_work.name.nil? || student_work.name.empty? ? student_work.user.show_name + '的作品' : student_work.name%>
<li class="chabox-w-151" ><%=student_work_name%></li>
<li><%=student_work.user.show_name%></li>
<li><%= student_work.user.user_extensions.nil? ? "--" : student_work.user.user_extensions.student_id%> </li>
<li class="chabox-r-line"><%= Time.parse(format_time(student_work.created_at)).strftime("%m-%d %H:%M")%></li>
<% if student_work.simi_id > 0 && @works_hash[student_work.simi_id] %>
<% simi_student_work = @works_hash[student_work.simi_id] %>
<% simi_student_work_name = simi_student_work.name.nil? || simi_student_work.name.empty? ? simi_student_work.user.show_name + '的作品' : simi_student_work.name%>
<li class="chabox-w-151"><%=simi_student_work_name%></li>
<li><%=simi_student_work.user.show_name%></li>
<li><%= simi_student_work.user.user_extensions.nil? ? "--" : simi_student_work.user.user_extensions.student_id%></li>
<li class="chabox-r-line"><%= Time.parse(format_time(simi_student_work.created_at)).strftime("%m-%d %H:%M")%></li>
<% if student_work.simi_value >= 90 %>
<li style = "color:red" ><%=student_work.simi_value%>%</li>
<% else %>
<li ><%=student_work.simi_value%>%</li>
<% end %>
<!--@works_hash[student_work.id].description -->
<!--<li ><a href="javascript:void(0);" target="_blank" class="cha-btn" onclick = "show_code_compare()">查看</a>-->
<li >
<%= link_to("查看", show_comparecode_course_path(:homework_id => @homework.id,:src_id => student_work.id,:dst_id => student_work.simi_id),:class => "cha-btn",:remote => true ) %>
</li>
<%else%>
<li class="chabox-w-151">无</li>
<li>--</li>
<li>--</li>
<li class="chabox-r-line">--</li>
<li >--</li>
<% end %>
</ul>
<%end%>
<%end%>
</div>
<div class="cl"></div>
</div>
<script type="text/javascript">
function show_code_compare() {
// $("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/show_compare_code' ,:locals => {:src_code=> 1,:src_name=> 2,:dst_name=> 3, :dst_code=> 4,:language=> 5,})%>');
// showModal('ajax-modal', '950px');
// $('#ajax-modal').siblings().remove();
// $('#ajax-modal').before("<a href='javascript:void(0)' onclick='closeModal();' style='margin-left: 935px;' class='resourceClose'></a>");
// $('#ajax-modal').parent().css("top", "20%").css("left", "26.5%").css("position", "absolute");
// $('#ajax-modal').parent().addClass("resourceUploadPopup");
// $('#ajax-modal').css("padding-left", "16px").css("padding-bottom", "16px");
//
// function closeModal() {
// hideModal($(".contrast-box"));
// }
}
</script>

View File

@ -0,0 +1,101 @@
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/show_compare_code' ,:locals => {:src_code=> @src_code,:src_name=> @src_username,:dst_name=> @dst_username, :dst_code=> @dst_code,})%>');
showModal('ajax-modal', '1250px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='closeModal();' style='margin-left: 1235px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","20%").css("left","20%").css("position","absolute");
//$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px").css("padding-top","10px");
function closeModal(){
hideModal($(".program-compare-code"));
}
var program_name = "text/x-csrc";
var language = <%= @homework.language.to_i %>;
if (language == 1) {
program_name = 'text/x-csrc';
} else if(language==2){
program_name = 'text/x-c++src';
}else if(language==3){
program_name = 'text/x-cython';
} else if(language==4){
program_name = 'text/x-java';
}
//
//var editor_1 = CodeMirror(document.getElementById("program-code_1"), {
// mode: {name: program_name,
// version: 2,
// singleLineStringErrors: false},
// lineNumbers: true,
// indentUnit: 2,
// matchBrackets: true,
// readOnly: true,
// value: $("#program-src_1").text()
// }
//);
//
//var editor_2 = CodeMirror(document.getElementById("program-code_2"), {
// mode: {name: program_name,
// version: 2,
// singleLineStringErrors: false},
// lineNumbers: true,
// indentUnit: 2,
// matchBrackets: true,
// readOnly: true,
// value: $("#program-src_2").text()
// }
//);
var value, orig1, orig2, dv, panes = 2, highlight = true, connect = null, collapse = false;
function initUI() {
if (value == null) return;
var target = document.getElementById("program-compare-code");
target.innerHTML = "";
dv = CodeMirror.MergeView(target, {
value: value,
origLeft: panes == 3 ? orig1 : null,
orig: orig2,
lineNumbers: true,
mode: program_name,
highlightDifferences: highlight,
connect: connect,
collapseIdentical: collapse
});
}
function toggleDifferences() {
dv.setShowDifferences(highlight = !highlight);
}
value = $("#program-src_1").text();
orig1 = $("#program-src_1").text();
orig2 = $("#program-src_2").text();
initUI();
function mergeViewHeight(mergeView) {
function editorHeight(editor) {
if (!editor) return 0;
return editor.getScrollInfo().height;
}
return Math.max(editorHeight(mergeView.leftOriginal()),
editorHeight(mergeView.editor()),
editorHeight(mergeView.rightOriginal()));
}
function resize(mergeView) {
var height = mergeViewHeight(mergeView);
for(;;) {
if (mergeView.leftOriginal())
mergeView.leftOriginal().setSize(null, height);
mergeView.editor().setSize(null, height);
if (mergeView.rightOriginal())
mergeView.rightOriginal().setSize(null, height);
var newHeight = mergeViewHeight(mergeView);
if (newHeight >= height) break;
else height = newHeight;
}
mergeView.wrap.style.height = height + "px";
}

View File

@ -39,7 +39,21 @@
<div class="homepageRight mt0 ml10">
<div class="homepageRightBanner mb10">
<div class="NewsBannerName">作业</div>
<!--<div class="NewsBannerName">作业</div>-->
<div id="menu_r" class="NewsBannerName" style="margin-bottom: -10px;">
<ul class="menu_r b_w" style="padding-left: 0px; margin-top: -5px;">
<li>
<a href="javascript:void(0);" class="parent" style="font-size:16px; color:#4b4b4b; font-weight: normal; padding-left: 0px;">作业</a>
<ul>
<% @homework_commons.each_with_index do |homework_common,index |%>
<li class="pr10">
<%= link_to "作业#{@homework_commons.count - index}#{homework_common.name}",student_work_index_path(:homework => homework_common.id)%>
</li>
<% end%>
</ul>
</li>
</ul>
</div>
<div id="search_div" class="fr mr10">
<%= render :partial => 'homework_search_form',:locals => {:course=>@course} %>
</div>

View File

@ -70,6 +70,6 @@
<% if courses.size == 5%>
<li class="homepageLeftMenuMore" id="user_show_more_course">
<input type="hidden" value="<%= page%>" id="course_page_num">
<a href="javascript:void(0);" class="homepageLeftMenuMoreIcon" onclick="show_more_course('<%= user_courses4show_user_path(user.id)%>');"></a>
<a href="javascript:void(0);" class="homepageLeftMenuMoreIcon" onclick="show_more_course('<%= user_courses4show_user_path(user.id)%>');"></a>
</li>
<% end%>

View File

@ -236,10 +236,10 @@
</div>
<% if @user.projects.visible.count > 0
project_order_ids = "(" +
ForgeActivity.find_by_sql("SELECT p.project_id, p.created_at FROM
(SELECT fa.project_id, MAX(fa.created_at) AS created_at FROM forge_activities fa WHERE fa.project_id IN (" + @user.projects.visible.select('projects.id').map{|p| p.id}.join(',') + ")
ForgeActivity.find_by_sql("SELECT p.project_id, p.updated_at FROM
(SELECT fa.project_id, MAX(fa.updated_at) AS updated_at FROM forge_activities fa WHERE fa.project_id IN (" + @user.projects.visible.select('projects.id').map{|p| p.id}.join(',') + ")
GROUP BY fa.project_id) AS p
ORDER BY p.created_at DESC limit 5").map {|p| p.project_id}.join(",") + ")"
ORDER BY p.updated_at DESC limit 5").map {|p| p.project_id}.join(",") + ")"
projects = Project.where("projects.id in #{project_order_ids}")
else
projects = []

View File

@ -30,7 +30,7 @@
<div class="fl">
<%=form_tag url_for(:controller => 'organizations', :action => 'join_courses', :organization_id => organization_id),:method => 'post', :id => 'join_courses_form', :remote => true,:class=>"resourcesSearchBox" do %>
<input type="text" name="courses" placeholder="搜索您已加入的课程的名称" class="searchCourse" />
<div id="search_courses_result_list" class="mb8"></div>
<div id="search_courses_result_list" class="mb8 maxHeight100" style="overflow:auto;"></div>
<div class="courseSendSubmit">
<a href="javascript:void(0);" onclick="org_join_courses(<%= organization_id %>);" class="sendSourceText">关联</a>
</div>

View File

@ -30,7 +30,7 @@
<div class="fl">
<%=form_tag url_for(:controller => 'organizations', :action => 'join_projects', :organization_id => organization_id),:method => 'post', :id => 'join_projects_form', :remote => true,:class=>"resourcesSearchBox" do %>
<input type="text" name="projects" placeholder="搜索您已加入的项目的名称" class="searchCourse" />
<div id="search_projects_result_list" class="mb8 maxHeight100"></div>
<div id="search_projects_result_list" class="mb8 maxHeight100" style="overflow:auto;"></div>
<div class="courseSendSubmit">
<a href="javascript:void(0);" onclick="org_join_projects(<%= organization_id %>);" class="sendSourceText">关联</a>
</div>

View File

@ -5,8 +5,8 @@
<li class="hworkPortrait mt15 mr10">
<%= link_to(image_tag(url_to_avatar(student_work.user),:width =>"40",:height => "40"),user_activities_path(student_work.user)) %>
</li>
<div onclick="show_student_work('<%= student_work_path(student_work)%>');" style="cursor: pointer;" class="student_work_<%= student_work.id%>">
<li class="hworkName mt15 mr15 <%= @homework.homework_type == 2 ? '' : 'width165'%>">
<div class="student_work_<%= student_work.id%>">
<li class="hworkName mt15 mr15 <%= @homework.homework_type == 2 ? '' : 'width165'%>" style="cursor: pointer;" onclick="show_student_work('<%= student_work_path(student_work)%>');">
<% student_work_name = student_work.name.nil? || student_work.name.empty? ? student_work.user.show_name + '的作品' : student_work.name%>
<div>
<%= link_to student_work_name,"javascript:void(0)" ,:title => student_work_name, :class => "linkGrey f14 StudentName break_word #{@homework.homework_type == 2 ? '' : 'width165'}"%>
@ -14,7 +14,7 @@
</li>
<li>
<% if @homework.homework_type != 3 %>
<ul class="mt10 fl">
<ul class="mt10 fl" style="cursor: pointer;" onclick="show_student_work('<%= student_work_path(student_work)%>');">
<li class="hworkStName mr10 mt16" title="<%= student_work.user.show_name%>">
<%= student_work.user.show_name%>
</li>
@ -24,9 +24,15 @@
</ul>
<% elsif @homework.homework_type == 3 && @homework.homework_detail_group.base_on_project == 1 %>
<ul class="mt10 fl">
<li class="hworkPrName mr10 mt12" title="项目名称">
<%= student_work.project.name %>
</li>
<% if student_work.project.is_public || User.current.member_of?(student_work.project) || User.current.admin? %>
<li class="hworkPrName mr10 mt12" title="项目名称">
<%= link_to( student_work.project.name, project_path(student_work.project.id))%>
</li>
<% else %>
<li class="hworkPrName mr10 mt12" title="该项目是私有的">
<%= student_work.project.name %>
</li>
<% end %>
</ul>
<% end %>
</li>
@ -57,7 +63,11 @@
<% if @homework.anonymous_comment == 0%>
<li class="hworkList50 <%= score_color student_work.student_score%> student_score_info">
<%= student_work.student_score.nil? ? "未参与" : format("%.1f",student_work.student_score)%>
<% if student_work.student_score.nil? %>
<span title="该作品未被匿评">未参与</span>
<% else %>
<%=format("%.1f",student_work.student_score) %>
<% end %>
<% unless student_work.student_score.nil?%>
<span class="linkBlue">
(<%= student_work.student_works_scores.where(:reviewer_role => 3).count%>)

View File

@ -1,10 +1,10 @@
<!-- 匿评作品列表,显示某一个作品的信息 -->
<ul class="hworkListRow" id="student_work_<%= student_work.id%>">
<% if @homework.homework_type != 3 %>
<% is_my_work = student_work.user == User.current%>
<% is_my_work = student_work.user == User.current%>
<% else %>
<% pro = @homework.student_work_projects.where(:user_id => User.current.id).first %>
<% is_my_work = pro && pro.student_work_id == student_work.id%>
<% pro = @homework.student_work_projects.where(:user_id => User.current.id).first %>
<% is_my_work = pro && pro.student_work_id == student_work.id%>
<% end %>
<li class="hworkList340 w465">
<ul>
@ -18,9 +18,9 @@
<%= link_to student_work_name, student_work_path(student_work),:remote => true,:title => student_work_name, :class => "linkGrey f14 StudentName break_word w230"%>
</div>
</li>
<li onclick="show_student_work('<%= student_work_path(student_work)%>');" style="cursor: pointer;" class="student_work_<%= student_work.id%>">
<li class="student_work_<%= student_work.id%>">
<% if @homework.homework_type != 3 %>
<ul class="mt10 fl">
<ul class="mt10 fl" onclick="show_student_work('<%= student_work_path(student_work)%>');" style="cursor: pointer;">
<li class="hworkStName mr10 mt16" title="<%= student_work.user.show_name%>">
<%= student_work.user.show_name%>
</li>
@ -30,9 +30,15 @@
</ul>
<% elsif @homework.homework_type == 3 && @homework.homework_detail_group.base_on_project == 1 %>
<ul class="mt10 fl">
<li class="hworkPrName mr10 mt12" title="项目名称">
<%= student_work.project.name %>
</li>
<% if student_work.project.is_public || User.current.member_of?(student_work.project) || User.current.admin? %>
<li class="hworkPrName mr10 mt12" title="项目名称">
<%= link_to( student_work.project.name, project_path(student_work.project.id))%>
</li>
<% else %>
<li class="hworkPrName mr10 mt12" title="该项目是私有的">
<%= student_work.project.name %>
</li>
<% end %>
</ul>
<% end %>
</li>

View File

@ -1,3 +1,4 @@
<div class="show_hwork_arrow"></div>
<div class="showHwork">
<ul>
@ -69,16 +70,14 @@
<span class="w60">正确输出:</span>
<span class="width120"><pre style="white-space: pre-wrap; margin-right: 15px;"><%=x["output"]%></pre></span>
<% if x["status"].to_i == 2 %>
<span class="w50">耗时:</span>
<span class="w80"><pre><%=x["time_used"]%>毫秒</pre></span>
<% end %>
<span class="w50">耗时:</span>
<span class="w80"><pre><%=x["time_used"]==0?1:x["time_used"]%>毫秒</pre></span>
<div class="cl"></div>
<% else %>
<span class="w60 c_green">测试正确!</span>
<!-- <span class="w50"> 耗时:</span> -->
<!-- <span class="w80"><pre><%=x["time_used"]%>微秒</pre></span> -->
<span style="width:360px;">&nbsp;</span>
<span class="w50">耗时:</span>
<span class="w80"><pre><%=x["time_used"]==0?1:x["time_used"]%>毫秒</pre></span>
<div class="cl"></div>
<% end %>
</li>

View File

@ -18,6 +18,9 @@
<input type="text" id="course_student_name" value="<%= @name%>" placeholder="姓名、学号、邮箱" class="hworkSearchInput" onkeypress="SearchByName('<%= student_work_index_path(:homework => @homework.id)%>',event);"/>
<a class="hworkSearchIcon" id="search_in_student_work" onclick="SearchByName_1('<%= student_work_index_path(:homework => @homework.id)%>');" href="javascript:void(0)"></a>
</div>
<%if @homework.homework_type == 2 %>
<a href="javascript:void(0);" class="BlueCirBtn fr" data-course-id="<%=@course.id%>" data-homework-simi-time="<%=@homework.simi_time%>" data-homework-id="<%=@homework.id%>" id="test-program-repeat-btn" onclick = "code_repeat()">代码查重</a>
<% end %>
<%= select_tag(:student_work_in_group,options_for_select(course_group_list(@course),@group), {:class => "classSplit"}) unless course_group_list(@course).empty? %>
<% end%>
<span class="fr c_grey"> <a href="javascript:void(0);" class="linkGrey2" id="homework_info_show" style="display: none">[ 显示作业信息 ]</a> </span>
@ -45,6 +48,7 @@
<div class="cl"></div>
<% end%>
<script type="text/javascript">
$(function(){
<% if !@is_evaluation && (!@is_teacher || params[:show_work_id].present?) %>
<% work= params[:show_work_id].nil? ? @homework.student_works.where("user_id = ?",User.current.id).first : StudentWork.find(params[:show_work_id]) %>
@ -85,4 +89,146 @@
<% end %>
<% end %>
});
//代码查重
function code_repeat(){
var homework_id = <%=@homework.id%>;
var course_id = <%=@course.id%>;
console.log("course_id=",course_id);
console.log("homework_id=",homework_id);
if(<%= @stundet_works.count <=1 %>)
{
//弹框
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起该作业的作品过少不能查重!",:status=>0, :homework=> @homework,:courseid=> @course.id})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
return;
}
//先请求下上次查询的时间
$.post(
'/student_work/last_codecomparetime',
{homework: homework_id},
function(data,status){
if (data.status == 0) {
var homework_simi_time = data.comparetime;
if (!homework_simi_time){
//没进行过代码查重则直接查重
test_repeat();
}
else{
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_1',:locals => {:homework=> @homework,:courseid=> @course.id })%>');
$('#compare-tips-1').html('您上次查重的时间为'+homework_simi_time);
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
console.log(homework_simi_time);
function closeModal(){
hideModal($(".blue-border-box"));
}
}
}
}
).fail(function(xhr, status){
// confirm("对不起,服务器繁忙请稍后再试!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起,服务器繁忙请稍后再试!",:status=>0, :homework=> @homework,:courseid=> @course.id})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
return;
});
//请求查重
var test_repeat = function(){
$.post(
'/student_work/code_repeattest',
{homework: homework_id},
function(data,status){
console.log("result = ");
console.log(data);
if (data.status == 0) {
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"查重完成是否立即查看结果?",:status=>1, :homework=> @homework,:courseid=> @course.id})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
}
else if (data.status == -1){
// confirm("对不起只支持java/c/c++的代码查重!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起目前只支持java/c/c++的代码查重!",:status=>0, :homework=> @homework,:courseid=> @course.id})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
}
else if (data.status == -2){
// confirm("对不起该作业的作品过少不能查重!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起该作业的作品过少不能查重!",:status=>0, :homework=> @homework,:courseid=> @course.id})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
}
return;
}
).fail(function(xhr, status){
// confirm("对不起,服务器繁忙请稍后再试!");
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'courses/compare_code_tips_2',:locals => {:des=>"对不起,服务器繁忙请稍后再试!",:status=>0, :homework=> @homework,:courseid=> @course.id})%>');
showModal('ajax-modal', '580px');
$('#ajax-modal').siblings().remove();
$('#ajax-modal').before("<a href='javascript:void(0)' onclick='hideModal();' style='margin-left: 560px;' class='resourceClose'></a>");
$('#ajax-modal').parent().css("top","40%").css("left","50%");
$('#ajax-modal').parent().addClass("resourceUploadPopup");
$('#ajax-modal').css("padding-left","16px").css("padding-bottom","16px");
function closeModal(){
hideModal($(".blue-border-box"));
}
return;
});
};
}
</script>

View File

@ -0,0 +1,2 @@

View File

@ -24,6 +24,8 @@
<%= submit_tag '',:class=>'searchIcon2',:onfocus=>"this.blur();",:style=>'border-style:none' %>
<% end %>
</div>
<div id="project_file_form">
<%= render :partial => 'users/project_file_form', :locals => {:user => user, :projects => projects, :send_id => send_id, :send_ids => send_ids, :type => type} %>
</div>

View File

@ -173,7 +173,7 @@
</div>
<% if !edit_mode || edit_mode && homework.homework_detail_manual.comment_status < 2 %>
<div class="fl f14 ml10" style="margin-top: 4px;">
<input type="checkbox" name="homework_common[anonymous_comment]" value="<%=edit_mode ? homework.anonymous_comment : 0 %>" id="anonymous_comment"/>
<input type="checkbox" name="homework_common[anonymous_comment]" value="<%=edit_mode ? homework.anonymous_comment : 1 %>" id="anonymous_comment"/>
<span class="f14 c_grey mr10">禁用匿评</span>
</div>
<% end %>

View File

@ -2,7 +2,6 @@
<%= javascript_include_tag "/assets/codemirror/codemirror_python_ruby_c" %>
<%= javascript_include_tag 'homework','baiduTemplate' %>
<%= stylesheet_link_tag "/assets/codemirror/codemirror" %>
<% end %>
<script type="text/javascript">
$(function(){
@ -36,16 +35,17 @@
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><!=results["result"]!> </pre></span>
<span class="w60">正确输出:</span>
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><!=results["output"]!></pre></span>
<! if(results["status"]==2){!>
<!--<! if(results["status"]==2){!>-->
<span class="w50"> 耗时:</span>
<span class="w80"><pre><!=results["time_used"]!>毫秒</pre></span>
<!}!>
<span class="w80"><pre><!=results["time_used"]==0?1:results["time_used"]!>毫秒</pre></span>
<!--<!}!>-->
<div class="cl"></div>
</li>
<!}else{!>
<span class="w60 c_green">测试正确!</span>
<!-- <span class="w50"> 耗时:</span> -->
<!-- <span class="w80"><pre><!=results["time_used"]!>微秒</pre></span> -->
<span style="width:480px;">&nbsp;</span>
<span class="w50"> 耗时:</span>
<span class="w80"><pre ><!=results["time_used"]==0?1:results["time_used"]!>毫秒</pre></span>
<div class="cl"></div>
</li>
@ -146,16 +146,17 @@
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><%=x["result"]%> </pre></span>
<span class="w60">正确输出:</span>
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><%= x["output"] %></pre></span>
<% if x["status"].to_i == 2 %>
<span class="w50"> 耗时:</span>
<span class="w80"><pre><%=x["time_used"]%>毫秒</pre></span>
<% end %>
<span class="w80"><pre><%=x["time_used"]==0?1:x["time_used"]%>毫秒</pre></span>
<div class="cl"></div>
</li>
<% else %>
<span class="w60 c_green">测试正确!</span>
<!-- <span class="w50"> 耗时:</span> -->
<!-- <span class="w80"><pre><%=x["time_used"]%>微秒</pre></span> -->
<span style="width:480px;">&nbsp;</span>
<span class="w50"> 耗时:</span>
<span class="w80"><pre><%=x["time_used"]==0?1:x["time_used"]%>毫秒</pre></span>
<div class="cl"></div>
</li>
<% end %>

View File

@ -1,3 +1,5 @@
<% if params[:is_observe].nil? %>
<% if params[:send_type].present? && params[:send_type] == 'news' %>
$("#ajax-modal").html('<%= escape_javascript( render :partial => 'users/share_news_to_project', :locals => {:projects => @projects, :user => @user, :send_id => @send_id, :send_ids => @send_ids}) %>');

View File

@ -25,16 +25,17 @@
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><!=results["result"]!> </pre></span>
<span class="w60">正确输出:</span>
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><!=results["output"]!></pre></span>
<! if(results["status"]==2){!>
<!--<! if(results["status"]==2){!>-->
<span class="w50"> 耗时:</span>
<span class="w80"><pre><!=results["time_used"]!>毫秒</pre></span>
<!}!>
<span class="w80"><pre><!=results["time_used"]==0?1:results["time_used"]!>毫秒</pre></span>
<!--<!}!>-->
<div class="cl"></div>
</li>
<!}else{!>
<span class="w60 c_green">测试正确!</span>
<!-- <span class="w50"> 耗时:</span> -->
<!-- <span class="w80"><pre><!=results["time_used"]!>微秒</pre></span> -->
<span style="width:480px;">&nbsp;</span>
<span class="w50"> 耗时:</span>
<span class="w80"><pre><!=results["time_used"]==0?1:results["time_used"]!>毫秒</pre></span>
<div class="cl"></div>
</li>
@ -113,16 +114,15 @@
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><%=x["result"]%> </pre></span>
<span class="w60">正确输出:</span>
<span class="w180"><pre style="white-space: pre-wrap; margin-right: 15px;"><%=x["output"]%></pre></span>
<% if x["status"].to_i == 2 %>
<span class="w50"> 耗时:</span>
<span class="w80"><pre><%=x["time_used"]%>毫秒</pre></span>
<% end %>
<span class="w50"> 耗时:</span>
<span class="w80"><pre><%=x["time_used"]==0?1:x["time_used"] %>毫秒</pre></span>
<div class="cl"></div>
</li>
<% else %>
<span class="w60 c_green">测试正确!</span>
<!--<span class="w50"> 耗时:</span> -->
<!--<span class="w80"><pre><%=x["time_used"]%>微秒</pre></span> -->
<span style="width:480px;">&nbsp;</span>
<span class="w50"> 耗时:</span>
<span class="w80"><pre><%=x["time_used"]==0?1:x["time_used"]%>毫秒</pre></span>
<div class="cl"></div>
</li>
<% end %>

View File

@ -7,7 +7,7 @@
<link rel="stylesheet" href="/stylesheets/weui/weui.min.css"/>
<script type="text/javascript">
function close(){
WeixinJSBridge.call('closeWindow');
window.close();
}
</script>

View File

@ -2123,4 +2123,30 @@ zh:
label_resource_download_times: 下载次数
label_resource_upload_author: 上传者
label_resource_belongs_course: 所属课程
label_resource_belongs_project: 所属项目
label_resource_belongs_project: 所属项目
#微信模板消息
label_new_homework_template: 您的课程有新作业了
label_update_homework_template: 您的作业已被修改
label_course_topic_template: 课程问答区有新帖子发布了
label_topic_comment_template: 您的帖子有新回复了
label_project_topic_template: 项目讨论区有新帖子发布了
label_issue_comment_template: 您的缺陷有新回复了
label_notice_comment_template: 您的课程通知有新回复了
label_news_comment_template: 您的项目新闻有新回复了
label_homework_comment_template: 您的作业有新回复了
label_new_journals_template: 您有新留言了
label_journals_comment_template: 您的留言有新回复了
label_blog_comment_template: 您的博客有新回复了
label_new_blog_template: 您的课程有新作业了
label_new_issue_template: 您有新缺陷了
label_new_notice_template: 您的课程有新通知了
label_resource_name: 您的课程有新作业了
label_resource_name: 您的课程有新作业了
label_resource_name: 您的课程有新作业了
label_resource_name: 您的课程有新作业了
label_resource_name: 您的课程有新作业了
label_resource_name: 您的课程有新作业了
#edit yk
label_code_work_tests: 代码测试列表

View File

@ -2,7 +2,7 @@ button:
-
type: "view"
name: "最新动态"
url: "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxc09454f171153c2d&redirect_uri=http://wechat.trustie.net/assets/wechat/app.html#/activities?response_type=code&scope=snsapi_base&state=123#wechat_redirect"
url: "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxc09454f171153c2d&redirect_uri=https://www.trustie.net/assets/wechat/app.html#/activities?response_type=code&scope=snsapi_base&state=123#wechat_redirect"
-
type: "click"
name: "意见返馈"
@ -13,7 +13,7 @@ button:
-
type: "view"
name: "进入网站"
url: "http://www.trustie.net/"
url: "https://www.trustie.net/"
-
type: "view"
name: "使用手册"

View File

@ -283,6 +283,8 @@ RedmineApp::Application.routes.draw do
get 'evaluation_list'
# post 'set_program_score'
post 'program_test_ex'
post 'code_repeattest'
post 'last_codecomparetime'
post 'set_score_rule'
end
end
@ -977,6 +979,7 @@ RedmineApp::Application.routes.draw do
match 'admin/latest_login_users', as: :latest_login_users
match 'admin/latest_login_teachers', as: :latest_login_teachers
get 'admin/homework'
get 'admin/code_work_tests'
resources :auth_sources do
member do
@ -997,6 +1000,7 @@ RedmineApp::Application.routes.draw do
get 'search_member', :action => 'search_member'
get 'file', :action => 'file', :as => 'file'
get 'feedback', :action => 'feedback', :as => 'course_feedback'
get 'code_repeat', :action => 'code_repeat', :as => 'code_repeat'
get 'member', :controller => 'courses', :action => 'member', :as => 'member'
get 'export_course_member_excel',:controller => 'courses',:action => 'export_course_member_excel'
get 'member_score', :to => 'courses#member_score'
@ -1023,10 +1027,10 @@ RedmineApp::Application.routes.draw do
get 'syllabus'
get 'search_public_orgs_not_in_course'
get "homework_search"
get "show_comparecode"
end
collection do
match 'join_private_courses', :via => [:get, :post]
end
match '/member', :to => 'courses#member', :as => 'member', :via => :get

View File

@ -0,0 +1,6 @@
class AddSimiIdToStudentWorks < ActiveRecord::Migration
def change
add_column :student_works, :simi_id, :integer, :default => false
add_column :student_works, :simi_value, :integer, :default => false
end
end

View File

@ -0,0 +1,5 @@
class AddSimiTimeToHomeworkCommons < ActiveRecord::Migration
def change
add_column :homework_commons, :simi_time, :datetime
end
end

View File

@ -395,6 +395,7 @@ Redmine::MenuManager.map :admin_menu do |menu|
menu.push :course_resource_list, {:controller => 'admin', :action => 'course_resource_list'}, :caption => :label_course_resource_list
menu.push :project_resource_list, {:controller => 'admin', :action => 'project_resource_list'}, :caption => :label_project_resource_list
menu.push :homework, {:controller => 'admin', :action => 'homework'}, :caption => :label_user_homework
menu.push :code_work_tests, {:controller => 'admin', :action => 'code_work_tests'}, :caption => :label_code_work_tests
end
#Modified by young

View File

@ -0,0 +1,113 @@
.CodeMirror-merge {
position: relative;
border: 1px solid #ddd;
white-space: pre;
}
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
height: 350px;
}
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 47%; }
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 6%; }
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
.CodeMirror-merge-pane {
display: inline-block;
white-space: normal;
vertical-align: top;
}
.CodeMirror-merge-pane-rightmost {
position: absolute;
right: 0px;
z-index: 1;
}
.CodeMirror-merge-gap {
z-index: 2;
display: inline-block;
height: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
position: relative;
background: #f8f8f8;
}
.CodeMirror-merge-scrolllock-wrap {
position: absolute;
bottom: 0; left: 50%;
}
.CodeMirror-merge-scrolllock {
position: relative;
left: -50%;
cursor: pointer;
color: #555;
line-height: 1;
}
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
position: absolute;
left: 0; top: 0;
right: 0; bottom: 0;
line-height: 1;
}
.CodeMirror-merge-copy {
position: absolute;
cursor: pointer;
color: #44c;
z-index: 3;
}
.CodeMirror-merge-copy-reverse {
position: absolute;
cursor: pointer;
color: #44c;
}
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
background-position: bottom left;
background-repeat: repeat-x;
}
.CodeMirror-merge-r-chunk { background: #ffffe0; }
.CodeMirror-merge-r-chunk-start { border-top: 1px solid #ee8; }
.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #ee8; }
.CodeMirror-merge-r-connect { fill: #ffffe0; stroke: #ee8; stroke-width: 1px; }
.CodeMirror-merge-l-chunk { background: #eef; }
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
.CodeMirror-merge-collapsed-widget:before {
content: "(...)";
}
.CodeMirror-merge-collapsed-widget {
cursor: pointer;
color: #88b;
background: #eef;
border: 1px solid #ddf;
font-size: 90%;
padding: 0 3px;
border-radius: 4px;
}
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }

View File

@ -0,0 +1,774 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); // Note non-packaged dependency diff_match_patch
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "diff_match_patch"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
var svgNS = "http://www.w3.org/2000/svg";
function DiffView(mv, type) {
this.mv = mv;
this.type = type;
this.classes = type == "left"
? {chunk: "CodeMirror-merge-l-chunk",
start: "CodeMirror-merge-l-chunk-start",
end: "CodeMirror-merge-l-chunk-end",
insert: "CodeMirror-merge-l-inserted",
del: "CodeMirror-merge-l-deleted",
connect: "CodeMirror-merge-l-connect"}
: {chunk: "CodeMirror-merge-r-chunk",
start: "CodeMirror-merge-r-chunk-start",
end: "CodeMirror-merge-r-chunk-end",
insert: "CodeMirror-merge-r-inserted",
del: "CodeMirror-merge-r-deleted",
connect: "CodeMirror-merge-r-connect"};
}
DiffView.prototype = {
constructor: DiffView,
init: function(pane, orig, options) {
this.edit = this.mv.edit;
(this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
this.orig.state.diffViews = [this];
this.diff = getDiff(asString(orig), asString(options.value));
this.chunks = getChunks(this.diff);
this.diffOutOfDate = this.dealigned = false;
this.showDifferences = options.showDifferences !== false;
this.forceUpdate = registerUpdate(this);
setScrollLock(this, true, false);
registerScroll(this);
},
setShowDifferences: function(val) {
val = val !== false;
if (val != this.showDifferences) {
this.showDifferences = val;
this.forceUpdate("full");
}
}
};
function ensureDiff(dv) {
if (dv.diffOutOfDate) {
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
dv.chunks = getChunks(dv.diff);
dv.diffOutOfDate = false;
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
}
}
var updating = false;
function registerUpdate(dv) {
var edit = {from: 0, to: 0, marked: []};
var orig = {from: 0, to: 0, marked: []};
var debounceChange, updatingFast = false;
function update(mode) {
updating = true;
updatingFast = false;
if (mode == "full") {
if (dv.svg) clear(dv.svg);
if (dv.copyButtons) clear(dv.copyButtons);
clearMarks(dv.edit, edit.marked, dv.classes);
clearMarks(dv.orig, orig.marked, dv.classes);
edit.from = edit.to = orig.from = orig.to = 0;
}
ensureDiff(dv);
if (dv.showDifferences) {
updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
}
makeConnections(dv);
if (dv.mv.options.connect == "align")
alignChunks(dv);
updating = false;
}
function setDealign(fast) {
if (updating) return;
dv.dealigned = true;
set(fast);
}
function set(fast) {
if (updating || updatingFast) return;
clearTimeout(debounceChange);
if (fast === true) updatingFast = true;
debounceChange = setTimeout(update, fast === true ? 20 : 250);
}
function change(_cm, change) {
if (!dv.diffOutOfDate) {
dv.diffOutOfDate = true;
edit.from = edit.to = orig.from = orig.to = 0;
}
// Update faster when a line was added/removed
setDealign(change.text.length - 1 != change.to.line - change.from.line);
}
dv.edit.on("change", change);
dv.orig.on("change", change);
dv.edit.on("markerAdded", setDealign);
dv.edit.on("markerCleared", setDealign);
dv.orig.on("markerAdded", setDealign);
dv.orig.on("markerCleared", setDealign);
dv.edit.on("viewportChange", function() { set(false); });
dv.orig.on("viewportChange", function() { set(false); });
update();
return update;
}
function registerScroll(dv) {
dv.edit.on("scroll", function() {
syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
});
dv.orig.on("scroll", function() {
syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
});
}
function syncScroll(dv, type) {
// Change handler will do a refresh after a timeout when diff is out of date
if (dv.diffOutOfDate) return false;
if (!dv.lockScroll) return true;
var editor, other, now = +new Date;
if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
else { editor = dv.orig; other = dv.edit; }
// Don't take action if the position of this editor was recently set
// (to prevent feedback loops)
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
var sInfo = editor.getScrollInfo();
if (dv.mv.options.connect == "align") {
targetPos = sInfo.top;
} else {
var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
var mid = editor.lineAtHeight(midY, "local");
var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
var ratio = (midY - off.top) / (off.bot - off.top);
var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
var botDist, mix;
// Some careful tweaking to make sure no space is left out of view
// when scrolling to top or bottom.
if (targetPos > sInfo.top && (mix = sInfo.top / halfScreen) < 1) {
targetPos = targetPos * mix + sInfo.top * (1 - mix);
} else if ((botDist = sInfo.height - sInfo.clientHeight - sInfo.top) < halfScreen) {
var otherInfo = other.getScrollInfo();
var botDistOther = otherInfo.height - otherInfo.clientHeight - targetPos;
if (botDistOther > botDist && (mix = botDist / halfScreen) < 1)
targetPos = targetPos * mix + (otherInfo.height - otherInfo.clientHeight - botDist) * (1 - mix);
}
}
other.scrollTo(sInfo.left, targetPos);
other.state.scrollSetAt = now;
other.state.scrollSetBy = dv;
return true;
}
function getOffsets(editor, around) {
var bot = around.after;
if (bot == null) bot = editor.lastLine() + 1;
return {top: editor.heightAtLine(around.before || 0, "local"),
bot: editor.heightAtLine(bot, "local")};
}
function setScrollLock(dv, val, action) {
dv.lockScroll = val;
if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da";
}
// Updating the marks for editor content
function clearMarks(editor, arr, classes) {
for (var i = 0; i < arr.length; ++i) {
var mark = arr[i];
if (mark instanceof CodeMirror.TextMarker) {
mark.clear();
} else if (mark.parent) {
editor.removeLineClass(mark, "background", classes.chunk);
editor.removeLineClass(mark, "background", classes.start);
editor.removeLineClass(mark, "background", classes.end);
}
}
arr.length = 0;
}
// FIXME maybe add a margin around viewport to prevent too many updates
function updateMarks(editor, diff, state, type, classes) {
var vp = editor.getViewport();
editor.operation(function() {
if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
clearMarks(editor, state.marked, classes);
markChanges(editor, diff, type, state.marked, vp.from, vp.to, classes);
state.from = vp.from; state.to = vp.to;
} else {
if (vp.from < state.from) {
markChanges(editor, diff, type, state.marked, vp.from, state.from, classes);
state.from = vp.from;
}
if (vp.to > state.to) {
markChanges(editor, diff, type, state.marked, state.to, vp.to, classes);
state.to = vp.to;
}
}
});
}
function markChanges(editor, diff, type, marks, from, to, classes) {
var pos = Pos(0, 0);
var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
var cls = type == DIFF_DELETE ? classes.del : classes.insert;
function markChunk(start, end) {
var bfrom = Math.max(from, start), bto = Math.min(to, end);
for (var i = bfrom; i < bto; ++i) {
var line = editor.addLineClass(i, "background", classes.chunk);
if (i == start) editor.addLineClass(line, "background", classes.start);
if (i == end - 1) editor.addLineClass(line, "background", classes.end);
marks.push(line);
}
// When the chunk is empty, make sure a horizontal line shows up
if (start == end && bfrom == end && bto == end) {
if (bfrom)
marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
else
marks.push(editor.addLineClass(bfrom, "background", classes.start));
}
}
var chunkStart = 0;
for (var i = 0; i < diff.length; ++i) {
var part = diff[i], tp = part[0], str = part[1];
if (tp == DIFF_EQUAL) {
var cleanFrom = pos.line + (startOfLineClean(diff, i) ? 0 : 1);
moveOver(pos, str);
var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
if (cleanTo > cleanFrom) {
if (i) markChunk(chunkStart, cleanFrom);
chunkStart = cleanTo;
}
} else {
if (tp == type) {
var end = moveOver(pos, str, true);
var a = posMax(top, pos), b = posMin(bot, end);
if (!posEq(a, b))
marks.push(editor.markText(a, b, {className: cls}));
pos = end;
}
}
}
if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
}
// Updating the gap between editor and original
function makeConnections(dv) {
if (!dv.showDifferences) return;
if (dv.svg) {
clear(dv.svg);
var w = dv.gap.offsetWidth;
attrs(dv.svg, "width", w, "height", dv.gap.offsetHeight);
}
if (dv.copyButtons) clear(dv.copyButtons);
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
for (var i = 0; i < dv.chunks.length; i++) {
var ch = dv.chunks[i];
if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
ch.origFrom <= vpOrig.to && ch.origTo >= vpOrig.from)
drawConnectorsForChunk(dv, ch, sTopOrig, sTopEdit, w);
}
}
function getMatchingOrigLine(editLine, chunks) {
var editStart = 0, origStart = 0;
for (var i = 0; i < chunks.length; i++) {
var chunk = chunks[i];
if (chunk.editTo > editLine && chunk.editFrom <= editLine) return null;
if (chunk.editFrom > editLine) break;
editStart = chunk.editTo;
origStart = chunk.origTo;
}
return origStart + (editLine - editStart);
}
function findAlignedLines(dv, other) {
var linesToAlign = [];
for (var i = 0; i < dv.chunks.length; i++) {
var chunk = dv.chunks[i];
linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
}
if (other) {
for (var i = 0; i < other.chunks.length; i++) {
var chunk = other.chunks[i];
for (var j = 0; j < linesToAlign.length; j++) {
var align = linesToAlign[j];
if (align[1] == chunk.editTo) {
j = -1;
break;
} else if (align[1] > chunk.editTo) {
break;
}
}
if (j > -1)
linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
}
}
return linesToAlign;
}
function alignChunks(dv, force) {
if (!dv.dealigned && !force) return;
if (!dv.orig.curOp) return dv.orig.operation(function() {
alignChunks(dv, force);
});
dv.dealigned = false;
var other = dv.mv.left == dv ? dv.mv.right : dv.mv.left;
if (other) {
ensureDiff(other);
other.dealigned = false;
}
var linesToAlign = findAlignedLines(dv, other);
// Clear old aligners
var aligners = dv.mv.aligners;
for (var i = 0; i < aligners.length; i++)
aligners[i].clear();
aligners.length = 0;
var cm = [dv.orig, dv.edit], scroll = [];
if (other) cm.push(other.orig);
for (var i = 0; i < cm.length; i++)
scroll.push(cm[i].getScrollInfo().top);
for (var ln = 0; ln < linesToAlign.length; ln++)
alignLines(cm, linesToAlign[ln], aligners);
for (var i = 0; i < cm.length; i++)
cm[i].scrollTo(null, scroll[i]);
}
function alignLines(cm, lines, aligners) {
var maxOffset = 0, offset = [];
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
var off = cm[i].heightAtLine(lines[i], "local");
offset[i] = off;
maxOffset = Math.max(maxOffset, off);
}
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
var diff = maxOffset - offset[i];
if (diff > 1)
aligners.push(padAbove(cm[i], lines[i], diff));
}
}
function padAbove(cm, line, size) {
var above = true;
if (line > cm.lastLine()) {
line--;
above = false;
}
var elt = document.createElement("div");
elt.className = "CodeMirror-merge-spacer";
elt.style.height = size + "px"; elt.style.minWidth = "1px";
return cm.addLineWidget(line, elt, {height: size, above: above});
}
function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
var flip = dv.type == "left";
var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
if (dv.svg) {
var topLpx = top;
var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
attrs(dv.svg.appendChild(document.createElementNS(svgNS, "path")),
"d", "M -1 " + topRpx + curveTop + " L " + (w + 2) + " " + botLpx + curveBot + " z",
"class", dv.classes.connect);
}
if (dv.copyButtons) {
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy"));
var editOriginals = dv.mv.options.allowEditingOriginals;
copy.title = editOriginals ? "Push to left" : "Revert chunk";
copy.chunk = chunk;
copy.style.top = top + "px";
if (editOriginals) {
var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy-reverse"));
copyReverse.title = "Push to right";
copyReverse.chunk = {editFrom: chunk.origFrom, editTo: chunk.origTo,
origFrom: chunk.editFrom, origTo: chunk.editTo};
copyReverse.style.top = topReverse + "px";
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
}
}
}
function copyChunk(dv, to, from, chunk) {
if (dv.diffOutOfDate) return;
var editStart = chunk.editTo > to.lastLine() ? Pos(chunk.editFrom - 1) : Pos(chunk.editFrom, 0)
var origStart = chunk.origTo > from.lastLine() ? Pos(chunk.origFrom - 1) : Pos(chunk.origFrom, 0)
to.replaceRange(from.getRange(origStart, Pos(chunk.origTo, 0)), editStart, Pos(chunk.editTo, 0))
}
// Merge view, containing 0, 1, or 2 diff views.
var MergeView = CodeMirror.MergeView = function(node, options) {
if (!(this instanceof MergeView)) return new MergeView(node, options);
this.options = options;
var origLeft = options.origLeft, origRight = options.origRight == null ? options.orig : options.origRight;
var hasLeft = origLeft != null, hasRight = origRight != null;
var panes = 1 + (hasLeft ? 1 : 0) + (hasRight ? 1 : 0);
var wrap = [], left = this.left = null, right = this.right = null;
var self = this;
if (hasLeft) {
left = this.left = new DiffView(this, "left");
var leftPane = elt("div", null, "CodeMirror-merge-pane");
wrap.push(leftPane);
wrap.push(buildGap(left));
}
var editPane = elt("div", null, "CodeMirror-merge-pane");
wrap.push(editPane);
if (hasRight) {
right = this.right = new DiffView(this, "right");
wrap.push(buildGap(right));
var rightPane = elt("div", null, "CodeMirror-merge-pane");
wrap.push(rightPane);
}
(hasRight ? rightPane : editPane).className += " CodeMirror-merge-pane-rightmost";
wrap.push(elt("div", null, null, "height: 0; clear: both;"));
var wrapElt = this.wrap = node.appendChild(elt("div", wrap, "CodeMirror-merge CodeMirror-merge-" + panes + "pane"));
this.edit = CodeMirror(editPane, copyObj(options));
if (left) left.init(leftPane, origLeft, options);
if (right) right.init(rightPane, origRight, options);
if (options.collapseIdentical)
this.editor().operation(function() {
collapseIdenticalStretches(self, options.collapseIdentical);
});
if (options.connect == "align") {
this.aligners = [];
alignChunks(this.left || this.right, true);
}
var onResize = function() {
if (left) makeConnections(left);
if (right) makeConnections(right);
};
CodeMirror.on(window, "resize", onResize);
var resizeInterval = setInterval(function() {
for (var p = wrapElt.parentNode; p && p != document.body; p = p.parentNode) {}
if (!p) { clearInterval(resizeInterval); CodeMirror.off(window, "resize", onResize); }
}, 5000);
};
function buildGap(dv) {
var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
lock.title = "Toggle locked scrolling";
var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
var gapElts = [lockWrap];
//去掉复制功能 yuanke20160408
// if (dv.mv.options.revertButtons !== false) {
// dv.copyButtons = elt("div", null, "CodeMirror-merge-copybuttons-" + dv.type);
// CodeMirror.on(dv.copyButtons, "click", function(e) {
// var node = e.target || e.srcElement;
// if (!node.chunk) return;
// if (node.className == "CodeMirror-merge-copy-reverse") {
// copyChunk(dv, dv.orig, dv.edit, node.chunk);
// return;
// }
// copyChunk(dv, dv.edit, dv.orig, node.chunk);
// });
// gapElts.unshift(dv.copyButtons);
// }
if (dv.mv.options.connect != "align") {
var svg = document.createElementNS && document.createElementNS(svgNS, "svg");
if (svg && !svg.createSVGRect) svg = null;
dv.svg = svg;
if (svg) gapElts.push(svg);
}
return dv.gap = elt("div", gapElts, "CodeMirror-merge-gap");
}
MergeView.prototype = {
constuctor: MergeView,
editor: function() { return this.edit; },
rightOriginal: function() { return this.right && this.right.orig; },
leftOriginal: function() { return this.left && this.left.orig; },
setShowDifferences: function(val) {
if (this.right) this.right.setShowDifferences(val);
if (this.left) this.left.setShowDifferences(val);
},
rightChunks: function() {
if (this.right) { ensureDiff(this.right); return this.right.chunks; }
},
leftChunks: function() {
if (this.left) { ensureDiff(this.left); return this.left.chunks; }
}
};
function asString(obj) {
if (typeof obj == "string") return obj;
else return obj.getValue();
}
// Operations on diffs
var dmp = new diff_match_patch();
function getDiff(a, b) {
var diff = dmp.diff_main(a, b);
dmp.diff_cleanupSemantic(diff);
// The library sometimes leaves in empty parts, which confuse the algorithm
for (var i = 0; i < diff.length; ++i) {
var part = diff[i];
if (!part[1]) {
diff.splice(i--, 1);
} else if (i && diff[i - 1][0] == part[0]) {
diff.splice(i--, 1);
diff[i][1] += part[1];
}
}
return diff;
}
function getChunks(diff) {
var chunks = [];
var startEdit = 0, startOrig = 0;
var edit = Pos(0, 0), orig = Pos(0, 0);
for (var i = 0; i < diff.length; ++i) {
var part = diff[i], tp = part[0];
if (tp == DIFF_EQUAL) {
var startOff = startOfLineClean(diff, i) ? 0 : 1;
var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
moveOver(edit, part[1], null, orig);
var endOff = endOfLineClean(diff, i) ? 1 : 0;
var cleanToEdit = edit.line + endOff, cleanToOrig = orig.line + endOff;
if (cleanToEdit > cleanFromEdit) {
if (i) chunks.push({origFrom: startOrig, origTo: cleanFromOrig,
editFrom: startEdit, editTo: cleanFromEdit});
startEdit = cleanToEdit; startOrig = cleanToOrig;
}
} else {
moveOver(tp == DIFF_INSERT ? edit : orig, part[1]);
}
}
if (startEdit <= edit.line || startOrig <= orig.line)
chunks.push({origFrom: startOrig, origTo: orig.line + 1,
editFrom: startEdit, editTo: edit.line + 1});
return chunks;
}
function endOfLineClean(diff, i) {
if (i == diff.length - 1) return true;
var next = diff[i + 1][1];
if (next.length == 1 || next.charCodeAt(0) != 10) return false;
if (i == diff.length - 2) return true;
next = diff[i + 2][1];
return next.length > 1 && next.charCodeAt(0) == 10;
}
function startOfLineClean(diff, i) {
if (i == 0) return true;
var last = diff[i - 1][1];
if (last.charCodeAt(last.length - 1) != 10) return false;
if (i == 1) return true;
last = diff[i - 2][1];
return last.charCodeAt(last.length - 1) == 10;
}
function chunkBoundariesAround(chunks, n, nInEdit) {
var beforeE, afterE, beforeO, afterO;
for (var i = 0; i < chunks.length; i++) {
var chunk = chunks[i];
var fromLocal = nInEdit ? chunk.editFrom : chunk.origFrom;
var toLocal = nInEdit ? chunk.editTo : chunk.origTo;
if (afterE == null) {
if (fromLocal > n) { afterE = chunk.editFrom; afterO = chunk.origFrom; }
else if (toLocal > n) { afterE = chunk.editTo; afterO = chunk.origTo; }
}
if (toLocal <= n) { beforeE = chunk.editTo; beforeO = chunk.origTo; }
else if (fromLocal <= n) { beforeE = chunk.editFrom; beforeO = chunk.origFrom; }
}
return {edit: {before: beforeE, after: afterE}, orig: {before: beforeO, after: afterO}};
}
function collapseSingle(cm, from, to) {
cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
var widget = document.createElement("span");
widget.className = "CodeMirror-merge-collapsed-widget";
widget.title = "Identical text collapsed. Click to expand.";
var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
inclusiveLeft: true,
inclusiveRight: true,
replacedWith: widget,
clearOnEnter: true
});
function clear() {
mark.clear();
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
}
CodeMirror.on(widget, "click", clear);
return {mark: mark, clear: clear};
}
function collapseStretch(size, editors) {
var marks = [];
function clear() {
for (var i = 0; i < marks.length; i++) marks[i].clear();
}
for (var i = 0; i < editors.length; i++) {
var editor = editors[i];
var mark = collapseSingle(editor.cm, editor.line, editor.line + size);
marks.push(mark);
mark.mark.on("clear", clear);
}
return marks[0].mark;
}
function unclearNearChunks(dv, margin, off, clear) {
for (var i = 0; i < dv.chunks.length; i++) {
var chunk = dv.chunks[i];
for (var l = chunk.editFrom - margin; l < chunk.editTo + margin; l++) {
var pos = l + off;
if (pos >= 0 && pos < clear.length) clear[pos] = false;
}
}
}
function collapseIdenticalStretches(mv, margin) {
if (typeof margin != "number") margin = 2;
var clear = [], edit = mv.editor(), off = edit.firstLine();
for (var l = off, e = edit.lastLine(); l <= e; l++) clear.push(true);
if (mv.left) unclearNearChunks(mv.left, margin, off, clear);
if (mv.right) unclearNearChunks(mv.right, margin, off, clear);
for (var i = 0; i < clear.length; i++) {
if (clear[i]) {
var line = i + off;
for (var size = 1; i < clear.length - 1 && clear[i + 1]; i++, size++) {}
if (size > margin) {
var editors = [{line: line, cm: edit}];
if (mv.left) editors.push({line: getMatchingOrigLine(line, mv.left.chunks), cm: mv.left.orig});
if (mv.right) editors.push({line: getMatchingOrigLine(line, mv.right.chunks), cm: mv.right.orig});
var mark = collapseStretch(size, editors);
if (mv.options.onCollapse) mv.options.onCollapse(mv, line, size, mark);
}
}
}
}
// General utilities
function elt(tag, content, className, style) {
var e = document.createElement(tag);
if (className) e.className = className;
if (style) e.style.cssText = style;
if (typeof content == "string") e.appendChild(document.createTextNode(content));
else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]);
return e;
}
function clear(node) {
for (var count = node.childNodes.length; count > 0; --count)
node.removeChild(node.firstChild);
}
function attrs(elt) {
for (var i = 1; i < arguments.length; i += 2)
elt.setAttribute(arguments[i], arguments[i+1]);
}
function copyObj(obj, target) {
if (!target) target = {};
for (var prop in obj) if (obj.hasOwnProperty(prop)) target[prop] = obj[prop];
return target;
}
function moveOver(pos, str, copy, other) {
var out = copy ? Pos(pos.line, pos.ch) : pos, at = 0;
for (;;) {
var nl = str.indexOf("\n", at);
if (nl == -1) break;
++out.line;
if (other) ++other.line;
at = nl + 1;
}
out.ch = (at ? 0 : out.ch) + (str.length - at);
if (other) other.ch = (at ? 0 : other.ch) + (str.length - at);
return out;
}
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
function findPrevDiff(chunks, start, isOrig) {
for (var i = chunks.length - 1; i >= 0; i--) {
var chunk = chunks[i];
var to = (isOrig ? chunk.origTo : chunk.editTo) - 1;
if (to < start) return to;
}
}
function findNextDiff(chunks, start, isOrig) {
for (var i = 0; i < chunks.length; i++) {
var chunk = chunks[i];
var from = (isOrig ? chunk.origFrom : chunk.editFrom);
if (from > start) return from;
}
}
function goNearbyDiff(cm, dir) {
var found = null, views = cm.state.diffViews, line = cm.getCursor().line;
if (views) for (var i = 0; i < views.length; i++) {
var dv = views[i], isOrig = cm == dv.orig;
ensureDiff(dv);
var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig);
if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found)))
found = pos;
}
if (found != null)
cm.setCursor(found, 0);
else
return CodeMirror.Pass;
}
CodeMirror.commands.goNextDiff = function(cm) {
return goNearbyDiff(cm, 1);
};
CodeMirror.commands.goPrevDiff = function(cm) {
return goNearbyDiff(cm, -1);
};
});

View File

@ -9,7 +9,11 @@
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{replaceUrl(act.author.img_url)}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{act.subject|safeHtml}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{act.author.realname}}</a>to<a herf="javascript:void(0);" class="ml10">{{act.course_project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;{{act.activity_type_name}}</a></div>
<div class="post-title hidden">
<a herf="javascript:void(0);" class="mr10">
<span ng-if="act.author.realname != ' '">{{act.author.realname}}</span>
<span ng-if="act.author.realname == ' '">{{act.author.nickname}}</span>
</a>to<a herf="javascript:void(0);" class="ml10">{{act.course_project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;{{act.activity_type_name}}</a></div>
<div class="cl"></div>
<div class="post-content c-grey2 mt10">
<div class="post-all-content" ng-bind-html="act.description|safeHtml"></div>

View File

@ -3,12 +3,11 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{blog.user.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{blog.title}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{blog.user.realname}}</a>发表博客</div>
<div class="post-title mb5"><span class="c-grey3 f15 fb">{{blog.title}}</span></div>
<div class="post-title"><a herf="javascript:void(0);" class="mr10">{{blog.user.realname}}</a>发表博客</div>
<div class="cl"></div>
<div class="post-content" style="height:auto;">
<div class="post-all-content c-grey2 mt10" ng-bind-html="blog.content|safeHtml"></div>
<div class="post-all-content c-grey3 mt10" ng-bind-html="blog.content|safeHtml"></div>
</div>
<div class="cl"></div>
<span class="c-grey f13 mt10 fl">{{blog.created_at}}</span>
@ -36,7 +35,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addBlogReply(formData)" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -3,11 +3,16 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{discussion.user.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{discussion.subject}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{discussion.user.realname}}</a>to<a herf="javascript:void(0);" class="ml10">{{discussion.course_project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;课程问答区</a></div>
<div class="cl"></div>
<div class="post-content c-grey2 mt10" style="height:auto;">
<div class="post-title mb5"><span class="c-grey3 f15 fb">{{discussion.subject}}</span></div>
<table class="post-detail-info"><tr>
<td class="text-nowrap v-top">发布者:</td>
<td>{{discussion.user.realname}}</td>
</tr>
<tr>
<td class="text-nowrap v-top">&nbsp;&nbsp;&nbsp;源:</td>
<td>{{discussion.course_project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;课程问答区</td>
</tr></table>
<div class="post-content c-grey3 mt10" style="height:auto;">
<div class="post-all-content" ng-bind-html="discussion.content|safeHtml"></div>
</div>
<div class="cl"></div>
@ -36,7 +41,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addDiscussionReply(formData)" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -3,11 +3,16 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{news.author.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{news.title}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{news.author.realname}}</a>to<a herf="javascript:void(0);" class="ml10">{{news.course_name}}&nbsp;&nbsp;|&nbsp;&nbsp;课程通知</a></div>
<div class="cl"></div>
<div class="post-content c-grey2 mt10" style="height:auto;">
<div class="post-title mb5"><span class="c-grey3 f15 fb">{{news.title}}</span></div>
<table class="post-detail-info"><tr>
<td class="text-nowrap v-top">发布者:</td>
<td>{{news.author.realname}}</td>
</tr>
<tr>
<td class="text-nowrap v-top">&nbsp;&nbsp;&nbsp;源:</td>
<td>{{news.course_name}}&nbsp;&nbsp;|&nbsp;&nbsp;课程通知</td>
</tr></table>
<div class="post-content c-grey3 mt10" style="height:auto;">
<div class="post-all-content" ng-bind-html="news.description|safeHtml"></div>
</div>
<div class="cl"></div>
@ -36,7 +41,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addNoticeReply(formData)" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -3,14 +3,23 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{homework.author.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{homework.name}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{homework.author.realname}}</a>to<a herf="javascript:void(0);" class="ml10">{{homework.course_name}}&nbsp;&nbsp;|&nbsp;&nbsp;课程作业</a></div>
<div class="cl"></div>
<div class="post-content c-grey2 mt10" style="height:auto;">
<div class="post-all-content" ng-bind-html="homework.description|safeHtml"></div>
<span class="mr15">迟交扣分:{{homework.late_penalty}}分</span> 匿评开启时间:{{homework.evaluation_start}}<br />
<span class="mr15">缺评扣分:{{homework.absence_penalty}}分/作品</span> 匿评关闭时间:{{homework.evaluation_end}}
<div class="post-title mb5"><span class="c-grey3 f15 fb">{{homework.name}}</span></div>
<table class="post-detail-info"><tr>
<td class="text-nowrap v-top">发布者:</td>
<td>
<span ng-if="homework.author.realname != ' '">{{homework.author.realname}}</span>
<span ng-if="homework.author.realname == ' '">{{homework.author.nickname}}</span></td>
</tr>
<tr>
<td class="text-nowrap v-top">&nbsp;&nbsp;&nbsp;源:</td>
<td>{{homework.course_name}}&nbsp;&nbsp;|&nbsp;&nbsp;课程作业</td>
</tr></table>
<div class="post-content c-grey3 mt10" style="height:auto;">
<div class="post-all-content mb10" ng-bind-html="homework.description|safeHtml"></div>
<span class="c-grey">迟交扣分:{{homework.late_penalty}}分<br/>
缺评扣分:{{homework.absence_penalty}}分/作品<br />
匿评开启时间:{{homework.evaluation_start}}<br />
匿评关闭时间:{{homework.evaluation_end}}</span>
</div>
<div class="cl"></div>
<span class="c-grey f13 mt10 fl">{{homework.publish_time}}</span>
@ -38,7 +47,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addHomeworkReply(formData)" value="回复" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -3,14 +3,21 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{issue.author.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{issue.subject}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{issue.author.realname}}</a>to<span class="ml10">{{issue.project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;项目缺陷</span></div>
<div class="cl"></div>
<div class="post-title mb5"><span class="c-grey3 f15 fb">{{issue.subject}}</span></div>
<table class="post-detail-info"><tr>
<td class="text-nowrap v-top">发布者:</td>
<td>{{issue.author.realname}}</td>
</tr>
<tr>
<td class="text-nowrap v-top">&nbsp;&nbsp;&nbsp;源:</td>
<td>{{issue.project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;项目缺陷</td>
</tr></table>
<div class="post-content" style="height:auto;">
<div class="post-all-content c-grey2 mt10" ng-bind-html="issue.description|safeHtml"></div>
<span class="mr15">状态:{{issue.issue_status}}</span> <span class="mr15">优先级:{{issue.issue_priority}}</span> <br />
<span class="mr15">指派给:{{issue.issue_assigned_to}}</span> <span class="mr15">完成度:{{issue.done_ratio}}%</span>
<div class="post-all-content c-grey3 mt10 mb10" ng-bind-html="issue.description|safeHtml"></div>
<span class="c-grey">&nbsp;&nbsp;&nbsp;态:{{issue.issue_status}}<br>
优先级:{{issue.issue_priority}}<br />
指派给:{{issue.issue_assigned_to}}<br />
完成度:{{issue.done_ratio}}%</span>
</div>
<div class="cl"></div>
<span class="c-grey f13 mt10 fl">{{issue.created_on}}</span>
@ -38,7 +45,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addIssueReply(formData)" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -2,9 +2,8 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{message.user.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title mb5 hidden"><a herf="javascript:void(0);" class="mr10">{{message.user.realname}}</a><span style="vertical-align:top;">给您留言了</span><br /></div>
<div class="post-title hidden">{{message.created_on}}</div>
<div class="post-title mb5"><a herf="javascript:void(0);" class="mr10">{{message.user.realname}}</a><span style="vertical-align:top;">给您留言了</span><br /></div>
<div class="post-title">{{message.created_on}}</div>
<div class="cl"></div>
<div class="post-content c-grey2 mt10" style="height:auto;">
<div class="post-all-content" ng-bind-html="message.notes|safeHtml"></div>
@ -34,7 +33,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addJournalReply(formData)" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -3,11 +3,16 @@
<div class="post-container">
<div class="post-wrapper">
<div class="post-main">
<div class="post-avatar fl"><img ng-src="{{discussion.user.img_url}}" width="45" height="45" class="border-radius" /></div>
<div class="post-title hidden mb5"><span class="c-grey3 f15 fb">{{discussion.subject}}</span></div>
<div class="post-title hidden"><a herf="javascript:void(0);" class="mr10">{{discussion.user.realname}}</a>to<a herf="javascript:void(0);" class="ml10">{{discussion.course_project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;项目讨论区</a></div>
<div class="cl"></div>
<div class="post-content c-grey2 mt10" style="height:auto;">
<div class="post-title mb5"><span class="c-grey3 f15 fb">{{discussion.subject}}</span></div>
<table class="post-detail-info"><tr>
<td class="text-nowrap v-top">发布者:</td>
<td>{{discussion.user.realname}}</td>
</tr>
<tr>
<td class="text-nowrap v-top">&nbsp;&nbsp;&nbsp;源:</td>
<td>{{discussion.course_project_name}}&nbsp;&nbsp;|&nbsp;&nbsp;项目讨论区</td>
</tr></table>
<div class="post-content c-grey3 mt10" style="height:auto;">
<div class="post-all-content" ng-bind-html="discussion.content|safeHtml"></div>
</div>
<div class="cl"></div>
@ -36,7 +41,9 @@
<div class="post-input-wrap">
<div class="post-reply-row">
<!--<div class="post-reply-avatar fl"><img src="images/post-avatar.jpg" width="30" height="30" /></div>-->
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
<div class="post-input-container">
<input type="text" class="post-reply-input" id="postInput" ng-model="formData.comment" />
</div>
<button ng-click="addDiscussionReply(formData)" class="post-reply-submit fr mt10">回复</button>
<div class="cl"></div>
</div>

View File

@ -1213,7 +1213,7 @@ function SearchByName(url,event)
}
function SearchByName_1(url)
{
//alert($("#student_work_in_group").val());
//alert($("#student_work_in_group").val());
$.get(
url,
{
@ -1431,5 +1431,4 @@ function submit_course_feedback() {
function show_more_tool(){
$('#navContentCourse').css('display', 'block');
}
}

View File

@ -98,11 +98,10 @@ $(function(){
if(status == 'timeout'){
alert("您的答案超时了, 请检查代码是否存在死循环的错误.");
} else {
alert("测试失败,服务器出错.");
alert("对不起,服务器繁忙请稍后再试!");
}
return;
});
};
test_post(1, 0);

View File

@ -1,16 +1,16 @@
var app = angular.module('wechat', ['ngRoute','ngCookies']);
var apiUrl = 'http://wechat.trustie.net/api/v1/';
var apiUrl = '/api/v1/';
var debug = false; //调试标志,如果在本地请置为true
if(debug===true){
apiUrl = 'http://localhost:3000/api/v1/';
apiUrl = 'https://www.trustie.net/api/v1/';
}
app.factory('auth', function($http,$routeParams, $cookies, $q){
var _openid = '';
if(debug===true){
_openid = "3";
_openid = "1";
}
var getOpenId = function() {
@ -63,7 +63,7 @@ app.factory('rms', function(){
app.controller('ActivityController',function($scope, $http, auth, rms, common){
$scope.replaceUrl = function(url){
return "http://www.trustie.net/" + url;
return url;
};
console.log("ActivityController load");

View File

@ -2848,3 +2848,26 @@ img.school_avatar {
.admin_message_warn{font-size: 12px;color: red;}
a.btn_message_free{ background:#15BCCF; display:block; text-align:center; color:#fff; padding:3px 0; width:60px; margin-bottom:10px;margin-left: 58px;}
/*20160401袁可------------------ 查重结果样式*/
.conbox{ width:1000px; margin:0 auto; border:1px solid #f0f0f0; background:#fff;}
.conbox-h2{ font-size:16px; padding:10px 0; padding-left:25px;}
.chabox{ width:1000px;}
.chabox ul li{ float:left; width:87px; text-align:center; display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.chabox ul li.chabox-w-151{ width:151px; display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.chabox ul li.chabox-r-line{ border-right:1px solid #D1D1D1;}
.chabox-top{ width:1000px; }
.chabox-top li{ font-size:14px; font-weight:bold; line-height:40px; height:40px; background:#E4E4E4; color:#000;}
.chabox-con li{font-size:12px; line-height:35px; height:35px; color:#000; border-bottom:1px solid #DFDFDF;}
a.cha-btn{ display:block; width:50px; height:20px; line-height:20px; margin:0 auto; border:1px solid #269ac9; color:#269ac9;-webkit-border-radius: 3px;border-radius:3px; margin-top:8px;}
a:hover.cha-btn{ background:#269ac9; color:#fff;}
.chabox-header li{ font-size:14px; font-weight:bold; line-height:40px; height:40px; border-top:1px solid #E4E4E4; border-right:1px solid #E4E4E4; color:#000;}
.chabox ul li.chabox-w-500{ width:499px;}
.contrast-box{ width:1200px;box-shadow: 0 0 5px #6B6B6B; background:#fff; margin:0 auto; }
.contrast-con{ width:599px; border-right:1px solid #D1D1D1; float:left;}
.contrast-con h3{font-size:14px; font-weight:bold; line-height:40px; height:40px; background:#E4E4E4; color:#000; text-align:center; display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.contrast-txt{ padding:10px;}
.showCodeC{ width:580px; float:left;}
.resourceClose {background:url(images/resource_icon_list.png) 0px -40px no-repeat; width:20px; height:20px; display:inline-block; position: absolute; z-index: 1000;}

View File

@ -1293,3 +1293,14 @@ a.contributor_course{float: right; color: #888; font-size: 12px; font-weight: no
/*20160310分班样式*/
.select-class-option {width:125px;}
/* 弹框 */
a.Blue-btn{ display:block; margin-right:15px;width:65px; height:22px; background-color:#ffffff; line-height:24px; vertical-align:middle; text-align:center; border:1px solid #3598db; color:#3598db; -moz-border-radius:5px; -webkit-border-radius:5px; border-radius:5px;}
a:hover.Blue-btn{ background:#3598db; color:#fff;}
.fl{ float:left;}
.fr{ float:right;}
.blue-border-box{ width:500px; padding:20px; margin:0 auto; background:#fff;}
.box-con h4{ font-size:14px; font-weight: bold; width:450px; text-align:center;}
.box-con{ width:450px; margin:0 auto; text-align:center;}
.box-con-a{ width:170px; margin:0 auto; margin-top:10px;}
/*--------------------------------------*/

View File

@ -226,7 +226,7 @@ a.c_green{ color:#28be6c;}
.c_dblue{ color:#09658c;}
.b_blue{background:#64bdd9;}
.b_green{background:#28be6c;}
.b_w{ background:#fff;}
.b_w{ background:#fff !important;}
/*add by Tim*/
.fontGrey {color:#cecece;}

View File

@ -33,6 +33,8 @@ a.underline {text-decoration:underline;}
.hidden {overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}
.inline-block {display:inline-block;}
.undis {display:none;}
.text-nowrap {white-space:nowrap;}
.v-top {vertical-align:top;}
/*动态样式*/
.post-container {width:100%;}
@ -40,6 +42,7 @@ a.underline {text-decoration:underline;}
.post-main {padding:10px; color:#9a9a9a;}
.post-avatar {width:45px; height:45px; margin-right:10px;}
.post-title {font-size:13px; text-align:left;}
.post-detail-info {font-size:13px; text-align:left; color:#9a9a9a;}
.fl {float:left;}
.fr {float:right;}
.cl {clear:both; overflow:hidden;}
@ -59,5 +62,6 @@ a.underline {text-decoration:underline;}
.post-reply-content {font-size:13px; text-align:left; word-break:break-all; word-wrap:break-word; overflow:hidden;}
.post-reply-date {font-size:13px;}
.post-reply-trigger {font-size:13px;}
.post-reply-input {width:100%; height:28px; line-height:28px; border:1px solid #e6e6e6; outline:none; border-radius:3px;}
.post-input-container {padding-right:2px;}
.post-reply-input {width:100%; height:28px; line-height:28px; border:1px solid #e6e6e6; outline:none; padding:0; margin:0; border-radius:3px;}
.post-reply-submit {font-size:13px; padding:3px 8px; color:#fff; background-color:#269ac9; outline:none; border:none; display:inline-block;}