Merge branch 'weixin_guange' into develop

This commit is contained in:
yuanke 2016-08-04 14:37:50 +08:00
commit 88c7018537
51 changed files with 4056 additions and 2799 deletions

View File

@ -100,15 +100,34 @@ module Mobile
params do
requires :token, type: String
requires :invite_code, type: String, desc: '邀请码'
requires :teacher_flag, type: Boolean
requires :assistant_flag, type: Boolean
requires :student_flag, type: Boolean
end
post "join" do
post "join_class" do
authenticate!
cs = CoursesService.new
status = cs.join_course({role: "10", openid: params[:openid], invite_code: params[:invite_code]}, current_user)
{
status: status[:state],
message:CoursesService::JoinCourseError.message(status[:state])
}
roles_ids = []
if params[:teacher_flag]
roles_ids << "9"
elsif params[:assistant_flag]
roles_ids << "7"
end
if params[:student_flag]
roles_ids << "10"
end
if roles_ids.length <= 0
{status:-1,message:"请至少选择一个角色"}
else
cs = CoursesService.new
status = cs.join_course_roles({role: roles_ids, openid: params[:openid], invite_code: params[:invite_code]}, current_user)
{
status: status[:state],
message:CoursesService::JoinCourseError.message(status[:state])
}
end
end
@ -166,7 +185,52 @@ module Mobile
present :status, 0
end
desc "设置教辅"
desc "课程未审核列表"
params do
requires :token, type: String
requires :course_id, type: Integer, desc: "课程id"
end
get 'reviewers' do
authenticate!
cs = CoursesService.new
reviewers = cs.reviewers_list(params[:course_id])
present :data, reviewers, with: Mobile::Entities::User
present :status, 0
end
desc "课程单个未审核用户信息"
params do
requires :token, type: String
requires :course_id, type: Integer, desc: "课程id"
requires :user_id, type: Integer, desc: "用户id"
end
post 'review_member_info' do
authenticate!
cs = CoursesService.new
reviewer = cs.get_reviewer_info(params)
present :data, reviewer, with: Mobile::Entities::User
present :status, 0
end
desc "处理教师或助教的身份申请"
params do
requires :token, type: String
requires :course_id, type: Integer, desc: "课程id"
requires :user_id, type: Integer, desc: "用户id"
requires :type, type: Integer, desc: "同意或拒绝"
end
post 'deal_join_apply' do
authenticate!
cs = CoursesService.new
result = cs.deal_join_apply(params,current_user)
present :status, result[:status]
present :message, result[:message]
end
desc "设置助教"
params do
requires :token,type:String
requires :user_id,type:Integer,desc: '用户id'
@ -178,7 +242,7 @@ module Mobile
present :status, 0
end
desc "删除"
desc "删除"
params do
requires :token,type:String
requires :user_id,type:Integer,desc: '用户id'
@ -448,20 +512,35 @@ module Mobile
requires :id, type: Integer
requires :token, type: String
requires :user_id, type: Integer
requires :role_id, type: Integer
requires :teacher_flag, type: Boolean
requires :assistant_flag, type: Boolean
requires :student_flag, type: Boolean
end
post 'edit_member_role' do
authenticate!
roles_id = []
if params[:teacher_flag]
roles_id << 9
elsif params[:assistant_flag]
roles_id << 7
end
if params[:student_flag]
roles_id << 10
end
c = Course.find("#{params[:id]}")
#7教辅 9教师 10学生
if c.tea_id == params[:user_id] || c.tea_id != current_user.id || !(params[:role_id] == 7 || params[:role_id] == 9 || params[:role_id] == 10)
if c.tea_id == params[:user_id] || c.tea_id != current_user.id || roles_id.length <= 0
present :status, -1
else
cs = CoursesService.new
status = cs.modify_user_course_role params
status = cs.modify_user_course_role params,roles_id
present :status, status
end
end

View File

@ -86,9 +86,24 @@ module Mobile
develop_members = project.member_principals.includes(:roles, :principal).where("member_roles.role_id=4").all.sort
report_members = project.member_principals.includes(:roles, :principal).where("member_roles.role_id=5").all.sort
review_master_members = []
review_develop_members = []
my_member = project.member_principals.where("users.id=#{current_user.id}").first
if my_member && my_member.roles[0] && my_member.roles[0].id == 3
ps = ProjectsService.new
user = current_user
review_master_members = ps.get_project_review_members(project,3,user)
review_develop_members = ps.get_project_review_members(project,4,user)
end
present :master_members,master_members, with: Mobile::Entities::ProjectMember
present :develop_members,develop_members, with: Mobile::Entities::ProjectMember
present :report_members,report_members, with: Mobile::Entities::ProjectMember
present :review_master_members,review_master_members
present :review_develop_members,review_develop_members
present :status, 0
end
@ -163,16 +178,55 @@ module Mobile
params do
requires :token, type: String
requires :invite_code, type: String, desc: '邀请码'
requires :role_id, type: Integer, desc: '身份'
end
post "join" do
post "join_project" do
authenticate!
# ps = ProjectsService.new
# status = ps.join_project({role: "5", openid: params[:openid], invite_code: params[:invite_code]}, current_user)
#
# present :status, status
role_id = params[:role_id]
{status:-1, message: '该功能将在近日开放,敬请期待!' }
if role_id != 3 && role_id != 4 && role_id != 5
{status:-1,message:"请至少选择一个角色"}
else
ps = ProjectsService.new
status = ps.join_project({role: role_id, openid: params[:openid], invite_code: params[:invite_code]}, current_user)
{status:status, message:ProjectsService::JoinProjectError.message(status)}
end
# {status:-1, message: '该功能将在近日开放,敬请期待!' }
end
desc "项目单个未审核用户信息"
params do
requires :token, type: String
requires :project_id, type: Integer, desc: "项目id"
requires :user_id, type: Integer, desc: "用户id"
end
post 'review_member_info' do
authenticate!
ps = ProjectsService.new
reviewer = ps.get_reviewer_info params
present :data, reviewer, with: Mobile::Entities::User
present :status, 0
end
desc "处理管理或开发的身份申请"
params do
requires :token, type: String
requires :project_id, type: Integer, desc: "项目id"
requires :user_id, type: Integer, desc: "用户id"
requires :type, type: Integer, desc: "同意或拒绝"
end
post 'deal_join_apply' do
authenticate!
ps = ProjectsService.new
result = ps.deal_join_apply(params,current_user)
present :status, result[:status]
present :message, result[:message]
end
end

View File

@ -85,7 +85,7 @@ module Mobile
#取二级回复的底楼层
parents_reply = []
parents_reply = get_reply_parents_no_root(parents_reply, c)
if parents_reply.count > 0 && parents_reply.count != 2 && !opt[:bottom]
if parents_reply.count > 0 && !opt[:bottom]
if opt[:type] == 1
# opt[:bottom] = true
# parents_reply[opt[:page]..opt[:page]]
@ -104,9 +104,9 @@ module Mobile
#取二级回复的顶楼层
parents_reply = []
parents_reply = get_reply_parents_no_root(parents_reply, c)
if parents_reply.count >= 2 && !opt[:top]
if parents_reply.count > 2 && !opt[:top]
if opt[:type] == 1
opt[:bottom] = true
opt[:top] = true
tStart = (opt[:page]-1)*5+2
tEnd = (opt[:page])*5+2 - 1
@ -125,6 +125,10 @@ module Mobile
parents_reply = parents_reply.reverse[0..1]
parents_reply.reverse
end
elsif parents_reply.count == 2 && !opt[:top]
opt[:top] = true
parents_reply = parents_reply.reverse[0..0]
parents_reply.reverse
else
[]
end

View File

@ -34,6 +34,8 @@ module Mobile
'Issue'
when :act_id
issue.id
when :title
issue.subject
end
end
end
@ -43,6 +45,7 @@ module Mobile
expose :description
expose :author, using: Mobile::Entities::User
expose :done_ratio
issue_expose :title
issue_expose :act_type
issue_expose :act_id
issue_expose :created_on

View File

@ -101,7 +101,7 @@ module Mobile
elsif opt[:comment_type] == "homework"
parents_reply = get_reply_parents(parents_reply, f)
end
if parents_reply.count > 0 && parents_reply.count != 2 && !opt[:bottom]
if parents_reply.count > 0 && !opt[:bottom]
if opt[:type] == 1
# opt[:bottom] = true
# parents_reply[opt[:page]..opt[:page]]
@ -125,9 +125,9 @@ module Mobile
elsif opt[:comment_type] == "homework"
parents_reply = get_reply_parents(parents_reply, f)
end
if parents_reply.count >= 2 && !opt[:top]
if parents_reply.count > 2 && !opt[:top]
if opt[:type] == 1
opt[:bottom] = true
opt[:top] = true
tStart = (opt[:page]-1)*5+2
tEnd = (opt[:page])*5+2 - 1
@ -146,6 +146,10 @@ module Mobile
parents_reply = parents_reply.reverse[0..1]
parents_reply.reverse
end
elsif parents_reply.count == 2 && !opt[:top]
opt[:top] = true
parents_reply = parents_reply.reverse[0..0]
parents_reply.reverse
else
[]
end

View File

@ -33,6 +33,8 @@ module Mobile
when :comment_count
all_comments = []
get_all_children(all_comments, u).count
when :title
u.subject
end
end
end
@ -50,6 +52,7 @@ module Mobile
message_expose :course_project_name
message_expose :board_id
message_expose :subject
message_expose :title
message_expose :content
message_expose :comment_count
message_expose :praise_count
@ -92,7 +95,7 @@ module Mobile
#取二级回复的底楼层
parents_reply = []
parents_reply = get_reply_parents_no_root(parents_reply, c)
if parents_reply.count > 0 && parents_reply.count != 2 && !opt[:bottom]
if parents_reply.count > 0 && !opt[:bottom]
if opt[:type] == 1
# opt[:bottom] = true
# parents_reply[opt[:page]..opt[:page]]
@ -111,9 +114,9 @@ module Mobile
#取二级回复的顶楼层
parents_reply = []
parents_reply = get_reply_parents_no_root(parents_reply, c)
if parents_reply.count >= 2 && !opt[:top]
if parents_reply.count > 2 && !opt[:top]
if opt[:type] == 1
opt[:bottom] = true
opt[:top] = true
tStart = (opt[:page]-1)*5+2
tEnd = (opt[:page])*5+2 - 1
@ -132,6 +135,10 @@ module Mobile
parents_reply = parents_reply.reverse[0..1]
parents_reply.reverse
end
elsif parents_reply.count == 2 && !opt[:top]
opt[:top] = true
parents_reply = parents_reply.reverse[0..0]
parents_reply.reverse
else
[]
end

View File

@ -4,8 +4,8 @@ module Mobile
expose :name
expose :id
expose :user_id
# expose :invite_code
# expose :qrcode
expose :invite_code
expose :qrcode
expose :can_setting, if: lambda { |instance, options| options[:user] } do |instance, options|
current_user = options[:user]

View File

@ -14,11 +14,11 @@ module Mobile
else
case f
when :roles_id
u.roles[0].id
# u.roles[0].id
u.roles.map {|r| r.id}
end
end
end
end
end

View File

@ -34,6 +34,8 @@ module Mobile
'HomeworkCommon'
when :act_id
wh.id
when :title
wh.name
end
end
end
@ -59,6 +61,7 @@ module Mobile
expose :quotes
expose :is_open
expose :id
whomework_expose :title
whomework_expose :act_type
whomework_expose :act_id
whomework_expose :course_name

View File

@ -10,8 +10,8 @@ class WechatsController < ActionController::Base
#邀请码
if join_class_request(request)
sendBindClass(request, {invite_code: content})
# elsif join_project_request(request)
# sendBindProject(request, {invite_code: content})
elsif join_project_request(request)
sendBindProject(request, {invite_code: content})
else
request.reply.text "您的意见已收到,非常感谢~ \n更多问题可以通过以下方式联系我们:\n官方QQ群173184401\n我们会认真聆听您的意见和建议。"
end
@ -49,7 +49,7 @@ class WechatsController < ActionController::Base
# When no any on :scan responder can match subscribe user scaned scene_id
on :event, with: 'scan' do |request|
if request[:EventKey].present?
sendBindClass(request, {ticket: request[:Ticket]})
checkTicket(request, {ticket: request[:Ticket]})
end
end
@ -149,13 +149,13 @@ class WechatsController < ActionController::Base
end
on :click, with: 'JOIN_PROJECT' do |request, key|
request.reply.text "该功能将在近日开放,敬请期待!"
# uw = user_binded?(request[:FromUserName])
# unless uw
# sendBind(request)
# else
# request.reply.text "请直接回复6位项目邀请码\n(不区分大小写):"
# end
# request.reply.text "该功能将在近日开放,敬请期待!"
uw = user_binded?(request[:FromUserName])
unless uw
sendBind(request)
else
request.reply.text "请直接回复6位项目邀请码\n(不区分大小写):"
end
end
on :click, with: 'JOIN_CLASS' do |request, key|
@ -209,6 +209,39 @@ class WechatsController < ActionController::Base
end
end
def checkTicket(request,params)
begin
uw = user_binded?(request[:FromUserName])
if !uw
return sendBind(request)
end
course = nil
course = Course.where(qrcode: params[:ticket]).first if params[:ticket]
course = Course.where(invite_code: params[:invite_code]).first if params[:invite_code]
if course
return join_class(params, uw.user, request)
else
project = nil
project = Project.where(qrcode: params[:ticket]).first if params[:ticket]
project = Project.where(invite_code: params[:invite_code]).first if params[:invite_code]
if project
return join_project(params, uw.user, request)
end
end
raise "该二维码已失效"
rescue => e
logger.error e.inspect
logger.error e.backtrace.join("\n")
return request.reply.text e
end
end
def default_msg(request)
uw = user_binded?(request[:FromUserName])
if uw && uw.user
@ -273,9 +306,9 @@ class WechatsController < ActionController::Base
role = 5
ps = ProjectsService.new
status = ps.join_project({invite_code: project.invite_code}, user)
if status[:state] != 0
raise ProjectService::JoinProjectError.message(status)
status = ps.join_project({role:5, invite_code: project.invite_code}, user)
if status != 0
raise ProjectsService::JoinProjectError.message(status)
end
creator = User.find(project.user_id)
@ -284,7 +317,7 @@ class WechatsController < ActionController::Base
content: "项目名称:#{project.name}\n发起人:#{creator.name}\n进入项目,和小伙伴轻松的研发吧!"} }
return request.reply.news(news) do |article, n, index| # article is return object
url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=#{Wechat.config.appid}&redirect_uri=#{ROOT_URL+'/wechat/user_activities#/project?id='+project.id.to_s}&response_type=code&scope=snsapi_base&state=myproject#wechat_redirect"
pic_url = "#{ROOT_URL}/images/wechat/class.jpg"
pic_url = "#{ROOT_URL}/images/wechat/project.jpg"
article.item title: "#{n[:title]}",
description: n[:content],
pic_url: pic_url,
@ -350,7 +383,15 @@ class WechatsController < ActionController::Base
render 'wechats/user_activities', layout: nil
end
def user_activities
@appid = Wechat.config.appid
## sign
@sign_params = wechat.jsapi_ticket.signature(current_url)
session[:wechat_code] = params[:code] if params[:code]
@path = '/'+(params[:state] || '')
open_id = get_openid_from_code(params[:code]) rescue
@ -398,6 +439,9 @@ class WechatsController < ActionController::Base
uw = UserWechat.where(openid: openid).first
end
def current_url
"#{request.protocol}#{request.host_with_port}#{request.fullpath}"
end
end

View File

@ -1,3 +1,4 @@
#coding=utf-8
class AppliedProject < ActiveRecord::Base
attr_accessible :project_id, :user_id, :role
@ -11,6 +12,14 @@ class AppliedProject < ActiveRecord::Base
def send_appliled_message
self.project.managers.each do |member|
self.applied_messages << AppliedMessage.new(:user_id => member.user_id, :status => true, :viewed => false, :applied_user_id => self.user_id, :role => self.role, :project_id => self.project_id)
#----------------微信通知----------------------
count = ShieldWechatMessage.where("container_type='User' and container_id=#{member.user_id} and shield_type='Project' and shield_id=#{self.project_id}").count
if count == 0
ws = WechatService.new
ws.project_review_notice member.user_id, "review_project_member", self.project_id, "项目成员审批通知", self.project.name, self.user.show_name, format_time(Time.now),"点击查看申请详情。",self.user.id
end
#--------------------------------------------
end
# end
end

View File

@ -928,6 +928,18 @@ class Project < ActiveRecord::Base
code
end
def generate_qrcode
ticket = self.qrcode
if !ticket || ticket.size < 10
response = Wechat.api.qrcode_create_scene(invite_code, 2592000)
logger.debug "response = #{response}"
self.qrcode = response['ticket']
save!
ticket = qrcode
end
ticket
end
private
def after_parent_changed(parent_was)

View File

@ -101,16 +101,149 @@ class CoursesService
gender = m.user.user_extensions.gender.nil? ? 0 : m.user.user_extensions.gender
work_unit = get_user_work_unit m.user
location = get_user_location m.user
users << {:id => m.user.id, :img_url => img_url, :nickname => m.user.login, :gender => gender,
:work_unit => work_unit, :mail => m.user.mail, :location => location,
role_name: m.roles.first.name,
name: m.user.show_name,
roles_id: m.roles[0].id,
:brief_introduction => m.user.user_extensions.brief_introduction,:realname=>m.user.realname}
role_ids = []
m.roles.each do |r|
role_ids << r.id
end
#双重身份 学生列表中不显示
unless (params[:role] == '2' && role_ids.length >= 2)
users << {:id => m.user.id, :img_url => img_url, :nickname => m.user.login, :gender => gender,
:work_unit => work_unit, :mail => m.user.mail, :location => location,
role_name: m.roles.first.name,
name: m.user.show_name,
roles_id: role_ids.include?(7) ? 7 : (role_ids.include?(9) ? 9 : 10 ),
:brief_introduction => m.user.user_extensions.brief_introduction,:realname=>m.user.realname}
end
end
users
end
def reviewers_list course_id
reviewers = []
c = Course.find(course_id)
if c
messages = CourseMessage.where("course_id=? and course_message_type = 'JoinCourseRequest' and status = 0 ",course_id)
messages.each do |m|
user = User.find(m.course_message_id)
if user
img_url = url_to_avatar(user)
gender = user.user_extensions.gender.nil? ? 0 : user.user_extensions.gender
work_unit = get_user_work_unit user
location = get_user_location user
roles_ids = m.content.split(",")
reviewers << {:id => user.id, :img_url => img_url, :nickname => user.login, :gender => gender,
:work_unit => work_unit, :mail => user.mail, :location => location,
role_name: "",
name: user.show_name,
roles_id: roles_ids.include?("7") ? 7 : 9,
:brief_introduction => user.user_extensions.brief_introduction,:realname=>user.realname}
end
end
end
reviewers
end
def get_reviewer_info params
info = nil
c = Course.find(params[:course_id])
if c
messages = CourseMessage.where("course_id=? and course_message_id = ? and course_message_type = 'JoinCourseRequest' and status = 0 ",params[:course_id],params[:user_id]).first
if messages
user = User.find(params[:user_id])
if user
img_url = url_to_avatar(user)
gender = user.user_extensions.gender.nil? ? 0 : user.user_extensions.gender
work_unit = get_user_work_unit user
location = get_user_location user
roles_ids = messages.content.split(",")
info = {:id => user.id, :img_url => img_url, :nickname => user.login, :gender => gender,
:work_unit => work_unit, :mail => user.mail, :location => location,
role_name: "",
name: user.show_name,
roles_id: roles_ids.include?("7") ? 7 : 9,
:brief_introduction => user.user_extensions.brief_introduction,:realname=>user.realname}
end
end
end
info
end
def deal_join_apply params,current_user
status = -1
message = ""
c = Course.find(params[:course_id])
if c
messages = CourseMessage.where("course_id=? and course_message_id = ? and course_message_type = 'JoinCourseRequest' and status = 0 ",params[:course_id],params[:user_id]).first
if messages
apply_user = User.find(params[:user_id])
ids = messages.content.split(",") # content保存的是申请的职位角色
integer_ids = []
ids.each do |role_id|
integer_ids << role_id.to_i
end
if params[:type] == 0
if apply_user.member_of_course?(c)
#将角色改为老师或者教辅
member = c.members.where(:user_id=>apply_user.id).all[0]
member.role_ids = integer_ids
#删除为学生的记录
unless member.role_ids.include?(10)
joined = StudentsForCourse.where('student_id = ? and course_id = ?', member.user_id,c.id)
joined.each do |join|
join.delete
end
end
member.course_group_id = 0
member.save
CourseMessage.create(:user_id => apply_user.id, :course_id => c.id, :viewed => false,:content=> messages.content,:course_message_id=>current_user.id,:course_message_type=>'CourseRequestDealResult',:status=>1)
messages.update_attributes(:status=>1,:viewed=>1)
else
members = []
members << Member.new(:role_ids => integer_ids, :user_id => apply_user.id)
c.members << members
CourseMessage.create(:user_id => apply_user.id, :course_id => c.id, :viewed => false,:content=> messages.content,:course_message_id=>current_user.id,:course_message_type=>'CourseRequestDealResult',:status=>1)
messages.update_attributes(:status=>1,:viewed=>1)
end
if integer_ids.include?(9)
message = "您已同意教师"+apply_user.show_name+",加入班级"
else
message = "您已同意助教"+apply_user.show_name+",加入班级"
end
else
CourseMessage.create(:user_id => apply_user.id, :course_id => c.id, :viewed => false,:content=> messages.content,:course_message_id=>current_user.id,:course_message_type=>'CourseRequestDealResult',:status=>2)
messages.update_attributes(:status=>2,:viewed=>1)
if integer_ids.include?(9)
message = "您已拒绝教师"+apply_user.show_name+",加入班级"
else
message = "您已拒绝助教"+apply_user.show_name+",加入班级"
end
end
status = 0
else
message = "该申请不存在或已被处理"
end
else
message = "该班级不存在或已被删除"
end
{:status => status,:message => message}
end
#获取用户的工作单位
def get_user_work_unit user
work_unit = ""
@ -329,15 +462,17 @@ class CoursesService
0, '加入成功',
1, '密码错误',
2, '班级已过期 请联系班级管理员重启班级。',
3, '您已经加入了班级',
3, '您已经是该班级的成员了',
4, '您的邀请码不正确',
5, '您还未登录',
6, '申请成功,请等待审核完毕',
6, '您的申请已提交,请等待管理员审批',
7, '您已经发送过申请了,请耐心等待',
8, '您已经是该班级的教师了',
9, '您已经是该班级的教辅了',
10, '您已经是该班级的管理员了',
11, '该班级不存在或已被删除啦',
12, '您已经发送过申请了,请耐心等待',
13, '您的申请已提交,请等待管理员审批',
'未知错误,请稍后再试'
]
end
@ -460,15 +595,31 @@ class CoursesService
is_stu = true
end
#如果已经发送过消息了,那么就要给个提示
if CourseMessage.where("course_message_type = 'JoinCourseRequest' and user_id = #{course.tea_id} and content = '#{role_str}' and course_message_id = #{User.current.id} and course_id = #{course.id} and status = 0").count != 0
if CourseMessage.where("course_message_type = 'JoinCourseRequest' and user_id = #{course.tea_id} and content = '#{role_str}' and course_message_id = #{current_user.id} and course_id = #{course.id} and status = 0").count != 0
if is_stu
@state = 12
else
@state = 7
end
else
Mailer.run.join_course_request(course, User.current, params[:role])
CourseMessage.create(:user_id => course.tea_id, :course_id => course.id, :viewed => false,:content=> role_str,:course_message_id=>User.current.id,:course_message_type=>'JoinCourseRequest',:status=>0)
Mailer.run.join_course_request(course, current_user, params[:role])
CourseMessage.create(:user_id => course.tea_id, :course_id => course.id, :viewed => false,:content=> role_str,:course_message_id=>current_user.id,:course_message_type=>'JoinCourseRequest',:status=>0)
#----------------微信通知----------------------
if role_ids.include?("7") || role_ids.include?("9")
tea_user = User.find(course.tea_id)
count = ShieldWechatMessage.where("container_type='User' and container_id=#{tea_user.id} and shield_type='Course' and shield_id=#{course.id}").count
if count == 0
rolename = role_ids.include?("7") ? "助教" : "教师"
content = current_user.show_name + "申请以"+rolename+"身份加入班级,等待您的审批。"
ws = WechatService.new
ws.class_notice tea_user.id, "review_class_member", course.id, "班级成员审批通知", course.name, tea_user.show_name, format_time(Time.now), content, "点击查看申请详情。",current_user.id
end
end
#--------------------------------------------
if is_stu
@state = 13
else
@ -1054,20 +1205,21 @@ class CoursesService
# end
#修改班级成员角色
def modify_user_course_role params
def modify_user_course_role params,roles_id
status = -1
c = Course.find("#{params[:id]}")
member = c.member_principals.includes(:roles, :principal).where("user_id=?",params[:user_id]).first
# member = c.member_principals.includes(:roles, :principal).where("user_id=?",params[:user_id]).first
member = c.members.where("user_id=?",params[:user_id]).first
if member
role = Role.find(params[:role_id])
member.role_ids = roles_id
member.member_roles[0].role_id = params[:role_id]
role = Role.find(roles_id[0])
# 这里的判断只能通过角色名,可以弄成常量
if params[:role_id] == 10
if roles_id && roles_id.include?(10)
StudentsForCourse.create(:student_id => params[:user_id], :course_id =>params[:id])
else
joined = StudentsForCourse.where('student_id = ? and course_id = ?', params[:user_id],params[:id])
@ -1090,7 +1242,7 @@ class CoursesService
Role.givable.all[3..5]
if member.member_roles[0].save
if member.save
status = 0
end
end

View File

@ -3,6 +3,9 @@
class ProjectsService
include ApplicationHelper
include ApiHelper
include ActionView::Helpers::DateHelper
include ProjectsHelper
#获取指定用户的项目列表
def user_projects(user)
@ -13,8 +16,8 @@ class ProjectsService
#显示项目
def show_project(params,current_user)
project = Project.find(params[:id])
# project.generate_invite_code
# project.generate_qrcode
project.generate_invite_code
project.generate_qrcode
project
end
@ -101,20 +104,22 @@ class ProjectsService
class JoinProjectError < Errors
define_error [
0, '加入成功',
0, '您已成功加入项目',
1, '您的邀请码不正确',
2, '您还未登录',
3, '您已经是该项目的管理人员',
4, '您已经是该项目的开发人员',
5, '您已经是该项目的报告人员',
6, '该项目不存在或已被删除啦',
7, '您的申请已提交,请等待管理员审批',
8, '您已经发送过申请了,请耐心等待',
'未知错误,请稍后再试'
]
end
def join_project params,current_user
status = -1
project = project.find_by_invite_code(params[:invite_code]) if params[:invite_code]
project = Project.find_by_invite_code(params[:invite_code]) if params[:invite_code]
if project
if project[:is_delete] == 1
@ -125,12 +130,31 @@ class ProjectsService
status = member.member_roles[0].role_id
else
if params[:invite_code].present?
members = []
members << Member.new(:role_ids => [5], :user_id => current_user.id)
project.members << members
projectInfo = ProjectInfo.new(:user_id => current_user.id, :project_id => project.id)
projectInfo.save
status = 0
if params[:role] == 5
members = []
user_grades = []
project_info = []
user_grades << UserGrade.new(:user_id => current_user.id, :project_id => project.id)
project.user_grades << user_grades unless user_grades.first.user_id.nil?
members << Member.new(:role_ids => ["5"], :user_id => current_user.id)
project.members << members
project_info << ProjectInfo.new(:user_id => current_user.id, :project_id => project.id)
project.project_infos << project_info
status = 0
else
if !AppliedProject.where(:project_id => project.id, :user_id => current_user.id).first.nil?
status = 8
else
AppliedProject.create(:user_id => current_user.id, :project_id => project.id, :role => params[:role])
status = 7
end
end
else
status = 4
end
@ -142,4 +166,126 @@ class ProjectsService
status
end
def get_project_review_members(project,role_id,current_user)
review_members = []
if role_id == 3 || role_id == 4
#AppliedMessage.where(:applied_id => @applied_message.applied_id, :project_id => @applied_message.project_id, :status => 1,
#:applied_type => "AppliedProject")
apply_messages = AppliedMessage.where(:user_id => current_user.id, :project_id => project.id, :status => 1, :role=>role_id)
apply_messages.each do |m|
user = User.find(m.applied_user_id)
if user
img_url = url_to_avatar(user)
gender = user.user_extensions.gender.nil? ? 0 : user.user_extensions.gender
work_unit = get_user_work_unit user
location = get_user_location user
review_members << {:id => user.id, :img_url => img_url, :nickname => user.login, :gender => gender,
:work_unit => work_unit, :mail => user.mail, :location => location,
role_name: "",
name: user.show_name,
roles_id: role_id,
:brief_introduction => user.user_extensions.brief_introduction,:realname=>user.realname,:real_name=>user.realname}
end
end
end
review_members
end
def get_reviewer_info params
info = nil
project = Project.find(params[:project_id])
if project
messages = AppliedProject.where(:project_id=> project.id, :user_id=>params[:user_id]).first
if messages
user = User.find(params[:user_id])
if user
img_url = url_to_avatar(user)
gender = user.user_extensions.gender.nil? ? 0 : user.user_extensions.gender
work_unit = get_user_work_unit user
location = get_user_location user
info = {:id => user.id, :img_url => img_url, :nickname => user.login, :gender => gender,
:work_unit => work_unit, :mail => user.mail, :location => location,
role_name: "",
name: user.show_name,
roles_id: messages.role,
:brief_introduction => user.user_extensions.brief_introduction,:realname=>user.realname}
end
end
end
info
end
def deal_join_apply params,current_user
status = -1
message = ""
project = Project.find(params[:project_id])
user = User.find(params[:user_id])
if project
applied_messages = AppliedMessage.where(:user_id => current_user.id, :project_id => project.id, :status => 1, :applied_user_id=>user.id,:applied_type => "AppliedProject")
apply_message = applied_messages.first
if apply_message
if user.member_of?(project)
message = "已经是该项目的成员了"
applied_messages.update_all(:status=>7)
else
applied_project = apply_message.applied
ap_role = applied_project.try(:role)
if ap_role
rolename = ap_role == 3 ? "管理人员" : "开发人员"
if params[:type] == 0
#同意
members = []
user_grades = []
project_info = []
members << Member.new(:role_ids => ["#{ap_role}"], :user_id => user.id)
user_grades << UserGrade.new(:user_id => user.id, :project_id => project.id)
role = Role.find(ap_role)
project_info << ProjectInfo.new(:project_id => project.id, :user_id => user.id) if role.allowed_to?(:is_manager)
project.members << members
project.project_infos << project_info
project.user_grades << user_grades unless user_grades.first.user_id.nil?
# 添加成功后所有管理员收到的消息状态都要更新
applied_messages.update_all(:status => 7, :viewed => true)
# 添加成功后,申请人收到消息
AppliedMessage.create(:user_id => user.id, :applied_type => "AppliedProject", :applied_id => applied_project.id ,
:status => 6, :viewed => false, :applied_user_id => current_user.id, :role => applied_project.role, :project_id => applied_project.project_id)
message = "您已同意"+rolename+user.show_name+",加入项目"
else
#拒绝
AppliedMessage.create(:user_id => user.id, :applied_type => "AppliedProject", :applied_id => applied_project.id ,:status => 4,
:viewed => false, :applied_user_id => current_user.id, :role => applied_project.role, :project_id => applied_project.project_id)
applied_messages.update_all(:status => 5, :viewed => true)
applied_project.delete
message = "您已拒绝"+rolename+user.show_name+",加入项目"
end
status = 0
else
message = "该申请不存在或已被处理"
end
end
else
message = "该申请不存在或已被处理"
end
else
message = "该项目不存在或已被删除"
end
{:status => status,:message => message}
end
end

View File

@ -139,11 +139,16 @@ class WechatService
data
end
def three_keys_template(openid, template_id, type, id, first, key1, key2, key3, remark="")
def three_keys_template(openid, template_id, type, id, first, key1, key2, key3, remark="",uid)
tmpurl = "#{Setting.protocol}://#{Setting.host_name}/wechat/user_activities#/#{type}/#{id}"
if uid && uid != 0
tmpurl = "#{Setting.protocol}://#{Setting.host_name}/wechat/user_activities#/#{type}?id=#{id}"+ "&user_id="+uid.to_s
end
data = {
touser:openid,
template_id:template_id,
url:"#{Setting.protocol}://#{Setting.host_name}/wechat/user_activities#/#{type}/#{id}",#/assets/wechat/app.html#/#{type}/#{id}
url:tmpurl,#/assets/wechat/app.html#/#{type}/#{id}
topcolor:"#FF0000",
data:{
first: {
@ -171,11 +176,16 @@ class WechatService
data
end
def four_keys_template(openid, template_id, type, id, first, key1, key2, key3, key4, remark="")
def four_keys_template(openid, template_id, type, id, first, key1, key2, key3, key4, remark="",uid)
tmpurl = "#{Setting.protocol}://#{Setting.host_name}/wechat/user_activities#/#{type}/#{id}"
if uid && uid != 0
tmpurl = "#{Setting.protocol}://#{Setting.host_name}/wechat/user_activities#/#{type}?id=#{id}"+ "&user_id="+uid.to_s
end
data = {
touser:openid,
template_id:template_id,
url:"#{Setting.protocol}://#{Setting.host_name}/wechat/user_activities#/#{type}/#{id}", #/assets/wechat/app.html#/#{type}/#{id}
url:tmpurl, #/assets/wechat/app.html#/#{type}/#{id}
topcolor:"#FF0000",
data:{
first: {
@ -269,10 +279,10 @@ class WechatService
end
end
def class_notice(user_id, type, id, first, key1, key2, key3, key4, remark="")
def class_notice(user_id, type, id, first, key1, key2, key3, key4, remark="",uid=0)
uw = UserWechat.where(user_id: user_id).first
unless uw.nil?
data = four_keys_template uw.openid,Wechat.config.class_notice, type, id, first, key1, key2, key3, key4, remark
data = four_keys_template uw.openid,Wechat.config.class_notice, type, id, first, key1, key2, key3, key4, remark, uid
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
@ -360,4 +370,17 @@ class WechatService
end
end
def project_review_notice(user_id, type, id, first, key1, key2,key3,remark="",uid=0)
uw = UserWechat.where(user_id: user_id).first
unless uw.nil?
data = three_keys_template uw.openid,Wechat.config.project_review_notice, type, id, first, key1, key2, key3, remark,uid
begin
req = Wechat.api.template_message_send Wechat::Message.to(uw.openid).template(data)
rescue Exception => e
Rails.logger.error "[project_review_notice] ===> #{e}"
end
Rails.logger.info "send over. #{req}"
end
end
end

View File

@ -12,15 +12,40 @@
<link type="text/css" rel="stylesheet" href="/stylesheets/weui/weui.min.css" />
<%= stylesheet_link_tag '/stylesheets/weui/weixin.css' %>
<script src="//res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script type="text/javascript">
window.g_debug = false; //调试标志,如果在本地请置为true
window.apiUrl = '/api/v1/';
window.g_redirect_path = '<%= @path %>';
window.g_localhost = "<%= Setting.protocol%>://"+"<%= Setting.host_name%>";
<% if @course_id %>
window.g_courseid = <%= @course_id %>;
<% elsif @project_id %>
window.g_projectid = <%= @project_id %>;
<% end %>
//参考文档
//https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
<% unless @sign_params.nil? %>
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来若要查看传入的参数可以在pc端打开参数信息会通过log打出仅在pc端时才会打印。
appId: '<%= @appid %>', // 必填,公众号的唯一标识
timestamp: <%= @sign_params[:timestamp] %>, // 必填,生成签名的时间戳
nonceStr: '<%= @sign_params[:noncestr] %>', // 必填,生成签名的随机串
signature: '<%= @sign_params[:signature] %>',// 必填签名见附录1
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone',
'hideOptionMenu','showOptionMenu','showMenuItems', 'hideMenuItems',
'hideAllNonBaseMenuItem','showAllNonBaseMenuItem','closeWindow', 'scanQRCode'] // 必填需要使用的JS接口列表所有JS接口列表见附录2
});
<% end %>
wx.ready(function(){
console.log("wx ready");
});
wx.error(function(err){
console.log(err);
});
</script>
</head>

View File

@ -3,6 +3,7 @@ require File.expand_path('../boot', __FILE__)
require 'rails/all'
require 'sprockets/railtie'
require 'elasticsearch/model'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
@ -83,9 +84,11 @@ module RedmineApp
end
end
config.wechat_srcs = ['app.js','others/factory.js','others/filter.js', 'controllers/*.js', 'directives/*.js', 'others/routes.js']
config.before_initialize do
config.middleware.use ::ResponseIp
end
config.after_initialize do

View File

@ -1,5 +1,15 @@
#coding=utf-8
#
require 'active_record'
## ruby2.3在这个rails版本的activerecord有bug, 直接用respond_to?(:to_proc)作判断
#而ruby2.3中hash可以返回 to_proc
if RUBY_VERSION > '2.3' && Rails.version < '3.2.22.3'
Hash.class_eval do
remove_method :to_proc
end
end
module ActiveRecord
class Base
include Redmine::I18n

View File

@ -23,13 +23,13 @@ button:
name: "更多"
sub_button:
-
type: "click"
type: "view"
name: "加入班级"
key: "JOIN_CLASS"
url: "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8e1ab05163a28e37&redirect_uri=https://www.trustie.net/wechat/user_activities&response_type=code&scope=snsapi_base&state=join_class#wechat_redirect"
-
type: "click"
type: "view"
name: "加入项目"
key: "JOIN_PROJECT"
url: "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8e1ab05163a28e37&redirect_uri=https://www.trustie.net/wechat/user_activities&response_type=code&scope=snsapi_base&state=join_project#wechat_redirect"
-
type: "view"
name: "历史推文"

View File

@ -23,13 +23,13 @@ button:
name: "更多"
sub_button:
-
type: "click"
type: "view"
name: "加入班级"
key: "JOIN_CLASS"
url: "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxc09454f171153c2d&redirect_uri=https://test.forge.trustie.net/wechat/user_activities&response_type=code&scope=snsapi_base&state=join_class#wechat_redirect"
-
type: "click"
type: "view"
name: "加入项目"
key: "JOIN_PROJECT"
url: "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxc09454f171153c2d&redirect_uri=https://test.forge.trustie.net/wechat/user_activities&response_type=code&scope=snsapi_base&state=join_project#wechat_redirect"
-
type: "view"
name: "历史推文"

View File

@ -22,7 +22,7 @@ default: &default
class_notice: "MQ_mFupbXP-9jWbeHT3C5xqNBvPo8EIlNv4ULakSpJA"
create_class_notice: "2GtJJGzzNlNy2i0UrsjEDlvfSVIUXQfSo47stpcQAVw"
create_project_notice: "jYu0iimbDpgWYZaTLXioZe2lvqoWTdKnUPyphTJ1mxs"
project_review_notice: "kdb-8UlMjTc3z51Qcf8g2vY4i_nE4OGKZAucdQma_2E"
production:
<<: *default

View File

@ -22,6 +22,7 @@ default: &default
class_notice: "8LVu33l6bP-56SDomVgHn-yJc57YpCwwJ81rAJgRONk"
create_class_notice: "9CDIvHIKiGwPEQWRw_-wieec1o50tMXQPPZIfECKu0I"
create_project_notice: "R2ZaQKJfDJgujPcHWPzadKHIRkIyj2CjX2o_qIuRqig"
project_review_notice: "cwpAHzdrYQo0Gc5ZKCBHMYEe8NjlOF6KpMGklMch8RM"
production:
<<: *default

File diff suppressed because it is too large Load Diff

20
lib/response_ip.rb Normal file
View File

@ -0,0 +1,20 @@
#coding=utf-8
#
require 'socket'
class ResponseIp
def initialize(app)
@app = app
end
def ip
addr = Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address rescue
addr || ''
end
def call(env)
status, headers, body = @app.call(env)
headers["X-response-ip"] = ip
[status, headers, body]
end
end

View File

@ -36,7 +36,7 @@
<script src="/javascripts/wechat/directives/form_validate.js"></script>
<script src="/javascripts/wechat/directives/input_auto.js"></script>
<script src="/javascripts/wechat/directives/loading_spinner.js"></script>
<!--<script src="/javascripts/wechat/directives/ellipsis.js"></script>-->
<script src="/javascripts/wechat/directives/ellipsis.js"></script>
<script src="/javascripts/wechat/controllers/reg.js"></script>
<script src="/javascripts/wechat/controllers/login.js"></script>
<script src="/javascripts/wechat/controllers/activity.js"></script>

View File

@ -34,9 +34,17 @@
<img ng-src="/images/wechat/{{teacher.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{teacher.name}}</span><img ng-src="/images/wechat/{{teacher.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<img src="/images/wechat/setting.png" ng-show = "course.is_creator && teacher.id != course.tea_id" width="15" class="fr mr10" style="margin-top:7px;" ng-click="onSetting(teacher)" />
<span class = "fr mr25 mt5" ng-show ="teacher.id == course.tea_id">管理员</span>
<span ng-class="['fr','mt5',{'mr10': course.is_creator,'mr25': !course.is_creator}]" ng-show ="teacher.id != course.tea_id && teacher.roles_id == 7"></span>
<span ng-class="['fr','mt5',{'mr10': course.is_creator,'mr25': !course.is_creator}]" ng-show ="teacher.id != course.tea_id && teacher.roles_id == 7"></span>
<div class="cl"></div>
</div>
<div ng-show ="course.is_creator" class="class-member-row f13 c-grey3" ng-repeat="reviewer in reviewers|filter:searchText">
<img ng-src="/images/wechat/{{reviewer.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{reviewer.name}}</span><img ng-src="/images/wechat/{{reviewer.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<span ng-click="review(reviewer)" class = "fr mr10 mt5 c-red">待审批 ▶</span>
<div class="cl"></div>
</div>
<div class="member-banner f13 mt10 c-grey3">我的同学</div>
<div class="class-member-row f13 c-grey3" ng-repeat="student in students|filter:searchText">
<img ng-src="/images/wechat/{{student.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{student.name}}</span><img ng-src="/images/wechat/{{student.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />

View File

@ -5,9 +5,9 @@
<div class="class-detail-row f13 c-grey3"><img ng-src="/images/wechat/{{current_edit_member.user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle mt4" /><span class="fl mt10 ml10">{{current_edit_member.user.realname == "" ? current_edit_member.user.name : current_edit_member.user.realname}}</span><img ng-src="/images/wechat/{{current_edit_member.user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt10" /><div class="cl"></div> </div>
<div class="course-list-row f13 c-grey3 mt10"><span class="fl ml10">角色</span></div>
<ul class="class-list f13 c-grey3">
<li><span class="fl ml10 class-list-name hidden">教师</span><span ng-click="selectRole(9)" ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle', {'checked': current_edit_member.roles_id == 9}]"></span></li>
<li><span class="fl ml10 class-list-name hidden"></span><span ng-click="selectRole(7)" ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle', {'checked': current_edit_member.roles_id == 7}]"></span></li>
<li class="border-bottom-none"><span class="fl ml10 class-list-name hidden">学生</span><span ng-click="selectRole(10)" ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle', {'checked': current_edit_member.roles_id == 10}]"></span></li>
<li><span class="fl ml10 class-list-name hidden">教师</span><span ng-click="selectRole(9)" ng-class="['login-box', 'fr', 'mr10', 'mt12', {'bg-grey':assistant,'checked': teacher}]"></span></li>
<li><span class="fl ml10 class-list-name hidden"></span><span ng-click="selectRole(7)" ng-class="['login-box', 'fr', 'mr10', 'mt12', {'bg-grey':teacher, 'checked': assistant}]"></span></li>
<li class="border-bottom-none"><span class="fl ml10 class-list-name hidden">学生</span><span ng-click="selectRole(10)" ng-class="['login-box', 'fr', 'mr10', 'mt12', {'checked': student}]"></span></li>
</ul>
<div class="bottom-tab-wrap mt10">
<a href="javascript:void(0);" ng-click="cancel()" class="weixin-tab c-grey border-top">取消</a>
@ -15,7 +15,5 @@
</div>
</div>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>

View File

@ -0,0 +1,28 @@
<div class="post-container">
<div loading-spinner></div>
<div class="post-container" style="padding-bottom:50px;">
<div class="blue-title">欢迎加入班级</div>
<div class="course-list-row f13 c-grey3 mt30"><span class="fl ml15 c-grey3">班级邀请码</span><input class="new-class-input ml25" ng-model="invite_code" required placeholder="请输入5位邀请码" /></div>
<div class="course-list-row f13 c-grey3 mt10"><span class="fl ml15">角色</span></div>
<ul class="class-list f13 c-grey3">
<li><span class="fl ml10 class-list-name hidden">教师</span><span ng-click="selectRole(9)" ng-class="['login-box', 'fr', 'mr10', 'mt12', {'bg-grey':assistant,'checked': teacher}]"></span></li>
<li><span class="fl ml10 class-list-name hidden">助教</span><span ng-click="selectRole(7)" ng-class="['login-box', 'fr', 'mr10', 'mt12', {'bg-grey':teacher, 'checked': assistant}]"></span></li>
<li class="border-bottom-none"><span class="fl ml10 class-list-name hidden">学生</span><span ng-click="selectRole(10)" ng-class="['login-box', 'fr', 'mr10', 'mt12', {'checked': student}]"></span></li>
</ul>
<div class="f12 c-grey6 mt10 ml15">
<span class="f13 fb c-grey3">提示</span>
<ul class="mb15 mt5 ml10 new-tip">
<li><span class="project-intro-dot"></span>教师、助教角色需要班级管理员审批</li>
<li><span class="project-intro-dot"></span>学生角色无需管理员审批</li>
</ul>
</div>
<div class="bottom-tab-wrap mt10">
<a href="javascript:void(0);" ng-click="cancel()" class="weixin-tab c-grey border-top">取消</a>
<a href="javascript:void(0);" ng-click="joinClass()" class="weixin-tab link-blue2 border-top">确定</a>
</div>
</div>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>

View File

@ -0,0 +1,20 @@
<div class="post-container">
<div loading-spinner></div>
<div class="post-container" style="padding-bottom:50px;">
<div class="blue-title">欢迎加入项目</div>
<div class="course-list-row f13 c-grey3 mt30"><span class="fl ml15 c-grey3">项目邀请码</span><input class="new-class-input ml25" ng-model="invite_code" required placeholder="请输入6位邀请码" /></div>
<div class="course-list-row f13 c-grey3 mt10"><span class="fl ml15">角色</span></div>
<ul class="class-list f13 c-grey3">
<li><span class="fl ml10 class-list-name hidden">管理人员</span><span ng-click="selectRole(3)" ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle', {'checked': role_id == 3}]"></span></li>
<li><span class="fl ml10 class-list-name hidden">开发人员</span><span ng-click="selectRole(4)" ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle', {'checked': role_id == 4}]"></span></li>
<li class="border-bottom-none"><span class="fl ml10 class-list-name hidden">报告人员</span><span ng-click="selectRole(5)" ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle', {'checked': role_id == 5}]"></span></li>
</ul>
<div class="bottom-tab-wrap mt10">
<a href="javascript:void(0);" ng-click="cancel()" class="weixin-tab c-grey border-top">取消</a>
<a href="javascript:void(0);" ng-click="join_project()" class="weixin-tab link-blue2 border-top">确定</a>
</div>
</div>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>

View File

@ -1,26 +1,26 @@
<div class="post-container">
<div loading-spinner></div>
<div class="blue-title">新建项目</div>
<form novalidate name="classForm">
<div class="course-list-row f13 c-grey3 mt30"><span class="fl ml15 c-grey3">项目名称</span><input class="new-class-input ml25" ng-model="project.name" required placeholder="如:团队协作方法与机制研究" /></div>
<a ng-click="newProject(classForm, project)" ng-class="['finish-btn', {'btn-disabled':!classForm.$valid} ]" >完成</a>
<div class="post-container">
<div loading-spinner></div>
<div class="blue-title">新建项目</div>
<form novalidate name="classForm">
<div class="course-list-row f13 c-grey3 mt30"><span class="fl ml15 c-grey3">项目名称</span><input class="new-class-input ml25" ng-model="project.name" required placeholder="如:团队协作方法与机制研究" /></div>
<a ng-click="newProject(classForm, project)" ng-class="['finish-btn', {'btn-disabled':!classForm.$valid} ]" >完成</a>
<div class="f12 c-grey6 tac">
<span class="f13 fb c-grey3">项目功能特性(微信版)</span>
<ul class="project-intro mb15 mt5">
<li>创建项目、加入项目</li>
<li>邀请成员、修改角色</li>
<li>浏览、回复项目动态</li>
<li>点赞、分享项目动态</li>
</ul>
<span class="f13 fb c-grey3">更多项目特性(浏览器版)</span>
<ul class="project-intro mt5">
<li>发布任务、问题跟踪</li>
<li>代码托管、质量分析</li>
<li>资源分享、交流研讨</li>
</ul>
</div>
</form>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>
<span class="f13 fb c-grey3">项目功能特性(微信版)</span>
<ul class="project-intro mb15 mt5">
<li><span class="project-intro-dot"></span>创建项目、加入项目</li>
<li><span class="project-intro-dot"></span>邀请成员、修改角色</li>
<li><span class="project-intro-dot"></span>浏览、回复项目动态</li>
<li><span class="project-intro-dot"></span>点赞、分享项目动态</li>
</ul>
<span class="f13 fb c-grey3">更多项目特性(浏览器版)</span>
<ul class="project-intro mt5">
<li><span class="project-intro-dot"></span>发布任务、问题跟踪</li>
<li><span class="project-intro-dot"></span>代码托管、质量分析</li>
<li><span class="project-intro-dot"></span>资源分享、交流研讨</li>
</ul>
</div>
</form>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>

View File

@ -5,7 +5,7 @@
<a ng-click="tab($index+1)" ng-repeat="menu in menus" id="class_tab_1" href="javascript:void(0);" ng-class="['weixin-tab', {'class-tab-active': currentTab == $index+1}]">{{menu}}</a>
</div>
<div ng-class="{'undis': currentTab != 1}">
<div ng-show="project" ng-class="{'undis': currentTab != 1}">
<div ng-repeat="act in project_activities">
<div ng-if="act.container_type=='Project' ">
<div ng-if="act.act_type=='Issue'">
@ -30,7 +30,7 @@
</div>
<div class="cl"></div>
</div>
<div class="post-dynamic-from hidden fl c-grey3">来源: <span class="c-blue">{{act.course_project_name}}</span></div>
<div class="fr f13">
<div ng-if="!act.praise_count" ng-click="addPraise(act);"><img src="/images/wechat/w_praise.png" width="20" style="vertical-align:top; margin-top:2px;" class="mr5" /><span></span></div>
<div ng-if="act.praise_count && !act.has_praise" ng-click="addPraise(act);"><img src="/images/wechat/w_praise.png" width="20" style="vertical-align:top; margin-top:2px;" class="mr5" /><span>{{act.praise_count}}</span></div>
@ -67,7 +67,7 @@
</div>
<div class="cl"></div>
</div>
<div class="post-dynamic-from hidden fl c-grey3">来源: <span class="c-blue">{{act.course_project_name}}</span></div>
<div class="fr f13">
<div ng-if="!act.praise_count" ng-click="addPraise(act);"><img src="/images/wechat/w_praise.png" width="20" style="vertical-align:top; margin-top:2px;" class="mr5" /><span></span></div>
<div ng-if="act.praise_count && !act.has_praise" ng-click="addPraise(act);"><img src="/images/wechat/w_praise.png" width="20" style="vertical-align:top; margin-top:2px;" class="mr5" /><span>{{act.praise_count}}</span></div>
@ -102,7 +102,7 @@
</div>
</div>
<div ng-class="{'undis': currentTab != 2}">
<div ng-show="project" ng-class="{'undis': currentTab != 2}">
<div class="class-search-wrap">
<div class="class-search-inner"> <img src="/images/wechat/search.png" width="18" class="class-search-icon" />
<input class="class-detail-search" ng-model="searchText" placeholder="输入关键词进行搜索" />
@ -110,16 +110,27 @@
</div>
<div class="member-banner f13 c-grey3">管理人员({{project_master_members.length}})</div>
<div class="class-member-row f13 c-grey3" ng-repeat="master in project_master_members|filter:searchText">
<img ng-src="/images/wechat/{{master.user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{master.user.real_name == "" ? master.user.name : master.user.real_name }}</span><span class="fr mr10 c-grey2">{{teacher.role_name|identify}}</span><img ng-src="/images/wechat/{{master.user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<img ng-src="/images/wechat/{{master.user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{master.user.real_name == "" ? master.user.name : master.user.real_name }}</span><img ng-src="/images/wechat/{{master.user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<img src="/images/wechat/setting.png" ng-show = "master.user.id != project.user_id && project.can_setting" width="15" class="class-list-setting" ng-click="onSetting(master)" />
<div class="cl"></div>
</div>
<div ng-show="project.can_setting" class="class-member-row f13 c-grey3" ng-repeat="user in review_master_members|filter:searchText">
<img ng-src="/images/wechat/{{user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{user.real_name == "" ? user.name : user.real_name }}</span><span class="fr mr10 c-grey2"></span><img ng-src="/images/wechat/{{user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<span ng-click="review(user)" class = "fr mr10 mt5 c-red">待审批 ▶</span>
<div class="cl"></div>
</div>
<div class="member-banner f13 mt10 c-grey3">开发人员({{project_develop_members.length}})</div>
<div class="class-member-row f13 c-grey3" ng-repeat="develop in project_develop_members|filter:searchText">
<img ng-src="/images/wechat/{{develop.user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{develop.user.real_name == "" ? develop.user.name : develop.user.real_name}}</span><img ng-src="/images/wechat/{{develop.user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<img src="/images/wechat/setting.png" ng-show = "master.user.id != project.user_id && project.can_setting " width="15" class="class-list-setting" ng-click="onSetting(develop)" />
<div class="cl"></div>
</div>
<div ng-show="project.can_setting" class="class-member-row f13 c-grey3" ng-repeat="user in review_develop_members|filter:searchText">
<img ng-src="/images/wechat/{{user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{user.real_name == "" ? user.name : user.real_name}}</span><img ng-src="/images/wechat/{{user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />
<span ng-click="review(user)" class = "fr mr10 mt5 c-red">待审批 ▶</span>
<div class="cl"></div>
</div>
<div class="member-banner f13 mt10 c-grey3">报告人员({{project_report_members.length}})</div>
<div class="class-member-row f13 c-grey3" ng-repeat="report in project_report_members|filter:searchText">
<img ng-src="/images/wechat/{{report.user.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle" /><span class="fl ml10 mt5">{{report.user.real_name == "" ? report.user.name : report.user.real_name}}</span><img ng-src="/images/wechat/{{report.user.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt5" />

View File

@ -0,0 +1,18 @@
<div class="post-container">
<div loading-spinner></div>
<div ng-show="current_course && current_review_member " class="post-container" style="padding-bottom:50px;">
<div class="blue-title">{{current_course.name}}</div>
<div class="class-detail-row f13 c-grey3"><img ng-src="/images/wechat/{{current_review_member.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle mt4" /><span class="fl mt10 ml10">{{current_review_member.realname == "" ? current_review_member.name : current_review_member.realname}}</span><img ng-src="/images/wechat/{{current_review_member.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt10" /><div class="cl"></div> </div>
<div class="course-list-row f13 c-grey3 mt10"><span class="fl ml10">角色</span></div>
<ul class="class-list f13 c-grey3">
<li><span class="fl ml10 class-list-name hidden">教师</span><span ng-class="['login-box', 'fr', 'mr10', 'mt12', {'bg-grey':current_review_member.roles_id == 7,'checked': current_review_member.roles_id == 9}]"></span></li>
<li class="border-bottom-none"><span class="fl ml10 class-list-name hidden">助教</span><span ng-class="['login-box', 'fr', 'mr10', 'mt12', {'bg-grey':current_review_member.roles_id == 9, 'checked': current_review_member.roles_id == 7}]"></span></li>
</ul>
<div class="bottom-tab-wrap mt10">
<a href="javascript:void(0);" ng-click="deal(1)" class="weixin-tab c-grey border-top">拒绝</a>
<a href="javascript:void(0);" ng-click="deal(0)" class="weixin-tab link-blue2 border-top">同意</a>
</div>
</div>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>

View File

@ -0,0 +1,19 @@
<div class="post-container">
<div loading-spinner></div>
<div ng-show="current_review_member" class="post-container" style="padding-bottom:50px;">
<div class="blue-title">{{project.name}}</div>
<div class="class-detail-row f13 c-grey3"><img ng-src="/images/wechat/{{current_review_member.gender==0 ? 'male' : 'female'}}.jpg" width="30" class="fl ml10 img-circle mt4" /><span class="fl mt10 ml10">{{current_review_member.realname == "" ? current_review_member.name : current_review_member.realname}}</span><img ng-src="/images/wechat/{{current_review_member.gender==0 ? 'male' : 'female'}}.png" width="15" class="fl ml10 mt10" /><div class="cl"></div> </div>
<div class="course-list-row f13 c-grey3 mt10"><span class="fl ml10">角色</span></div>
<ul class="class-list f13 c-grey3">
<li><span class="fl ml10 class-list-name hidden">管理人员</span><span ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle',{'bg-grey':current_review_member.roles_id == 4,'checked': current_review_member.roles_id == 3}]"></span></li>
<li class="border-bottom-none"><span class="fl ml10 class-list-name hidden">开发人员</span><span ng-class="['login-box', 'fr', 'mr10', 'mt12','img-circle',{'bg-grey':current_review_member.roles_id == 3,'checked': current_review_member.roles_id == 4}]"></span></li>
</ul>
<div class="bottom-tab-wrap mt10">
<a href="javascript:void(0);" ng-click="deal(1)" class="weixin-tab c-grey border-top">拒绝</a>
<a href="javascript:void(0);" ng-click="deal(0)" class="weixin-tab link-blue2 border-top">同意</a>
</div>
</div>
<my-alert message="alertService.message" title="alertService.title" visible="alertService.visible" cb="alertService.cb"></my-alert>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -15,6 +15,17 @@ app.controller('ClassController', ['$scope', 'config','$http', 'auth','$location
)
}
if(vm.course.is_creator){
if(vm.reviewers.length<=0){
$http.get(config.apiUrl + 'courses/reviewers?token='+auth.token()+'&course_id='+courseid).then(
function(response) {
console.log(response.data);
vm.reviewers = response.data.data;
}
)
}
}
if(vm.students.length<=0){
$http.get(config.apiUrl + 'courses/students?token='+auth.token()+'&course_id='+courseid).then(
function(response) {
@ -100,6 +111,7 @@ app.controller('ClassController', ['$scope', 'config','$http', 'auth','$location
vm.course = {};
vm.students = [];
vm.teachers = [];
vm.reviewers = []; //待审批
vm.resources = [];
vm.homeworks = [];
vm.exercises = [];
@ -157,6 +169,12 @@ app.controller('ClassController', ['$scope', 'config','$http', 'auth','$location
$location.path("/edit_class_member").search({id: courseid,user_id: user.id});
};
vm.review = function(user){
rms.save('current_review_member', user);
rms.save('current_course', vm.course);
$location.path("/review_class_member").search({id: courseid,user_id: user.id});
}

View File

@ -16,6 +16,27 @@ app.controller('ClassListController', ['$scope', 'config', 'auth', '$http', '$lo
function (response) {
console.log(response.data);
vm.syllabuses = response.data.data;
var show_1 = false;
var show_2 = false;
for (var i in vm.syllabuses) {
if(vm.syllabuses[i].can_setting && vm.syllabuses[i].courses.length > 0 && show_1 == false ){
vm.syllabuses[i].show_plus = true;
show_1 = true;
}
if(!vm.syllabuses[i].can_setting && vm.syllabuses[i].courses.length > 0 && show_2 == false ){
vm.syllabuses[i].show_plus = true;
show_2 = true;
}
if(show_1 && show_2){
break;
}
}
rms.save('syllabuses', vm.syllabuses);
}
);
@ -25,7 +46,6 @@ app.controller('ClassListController', ['$scope', 'config', 'auth', '$http', '$lo
loadClassList();
}
vm.goClass = function (course_id) {
console.log(course_id);
$location.path("/class").search({id: course_id});
@ -33,45 +53,49 @@ app.controller('ClassListController', ['$scope', 'config', 'auth', '$http', '$lo
vm.newClass = function () {
//先判断下权限
$http.post(config.apiUrl + "syllabuses/auth",{token: auth.token()} ).then(
function (response) {
console.log(response.data);
if (response.data.auth == 0) {
vm.alertService_1.showMessage('提示', '非教师身份不能创建课程哦~');
}
else{
$location.path("/new_class");
}
}
);
}
// $http.post(config.apiUrl + "syllabuses/auth",{token: auth.token()} ).then(
// function (response) {
// console.log(response.data);
// if (response.data.auth == 0) {
// vm.alertService_1.showMessage('提示', '非教师身份不能创建课程哦~');
// }
// else{
// $location.path("/new_class");
// }
// }
// );
$location.path("/new_class");
};
vm.goResource = function () {
$location.path("/myresource");
}
};
vm.joinClass = function () {
vm.alertService_3.showMessage('提示', '请输入5位班级邀请码(不区分大小写)', function(){
if (vm.alertService_3.invite && vm.alertService_3.invite.length == 5) {
$http.post(config.apiUrl + "courses/join", {
token: auth.token(),
invite_code: vm.alertService_3.invite
}).then(function (response) {
console.log(response.data);
if (response.data.status != 0) {
vm.alertService_1.showMessage('提示', response.data.message);
} else {
vm.alertService_1.showMessage('提示', '加入课程成功');
vm.alertService_3.invite = "";
loadClassList();
}
});
} else {
if(vm.alertService_3.invite){
vm.alertService_1.showMessage('提示', '邀请码格式不正确');
}
}
});
// vm.alertService_3.showMessage('提示', '请输入5位班级邀请码(不区分大小写)', function(){
// if (vm.alertService_3.invite && vm.alertService_3.invite.length == 5) {
// $http.post(config.apiUrl + "courses/join", {
// token: auth.token(),
// invite_code: vm.alertService_3.invite
// }).then(function (response) {
// console.log(response.data);
// if (response.data.status != 0) {
// vm.alertService_1.showMessage('提示', response.data.message);
// } else {
// vm.alertService_1.showMessage('提示', '加入课程成功');
// vm.alertService_3.invite = "";
// loadClassList();
// }
// });
// } else {
// if(vm.alertService_3.invite){
// vm.alertService_1.showMessage('提示', '邀请码格式不正确');
// }
// }
// });
$location.path("/join_class").search({tag: 1});
};
vm.onSetting = function (syllabus) {

View File

@ -10,6 +10,16 @@ app.controller('EditClassMemberController', ['$scope', '$http', 'auth', 'config'
var course_id = $routeParams.id;
var user_id = $routeParams.user_id;
vm.teacher = false; //教师
vm.assistant = false; //教辅
vm.student = false; //学生.
vm.tmpteacher = false; //教师
vm.tmpassistant = false; //教辅
vm.tmpstudent = false; //学生
if(!vm.current_edit_member){
$http.post(config.apiUrl+'courses/get_member_info', {
token: auth.token(),
@ -19,54 +29,81 @@ app.controller('EditClassMemberController', ['$scope', '$http', 'auth', 'config'
if(response.data.status!=0){
vm.alertService.showMessage('提示', response.data.message);
} else {
console.log(response);
course_id = response.data.course_id;
user_id = response.data.user_id;
vm.current_edit_member = response.data.member_info;
vm.current_roles_id = vm.current_edit_member.roles_id;
for(var i in vm.current_roles_id){
if(vm.current_roles_id[i] == 9){
vm.teacher = true;
vm.tmpteacher = true;
}
else if(vm.current_roles_id[i] == 7){
vm.assistant = true;
vm.tmpassistant = true;
}
else if(vm.current_roles_id[i] == 10){
vm.student = true;
vm.tmpstudent = true;
}
}
}
});
}
console.log(vm.current_edit_member);
vm.cancel = function(){
vm.alertService.showMessage('提示', '您确定不对角色进行变更吗?', function(){
// rms.save("project_master_members",[]);
// rms.save("project_develop_members",[]);
// rms.save("project_report_members",[]);
window.history.back();
// $location.path("/project").search({id: project_id});
});
// vm.alertService.showMessage('提示', '您确定不对角色进行变更吗?', function(){
// window.history.back();
// });
window.history.back();
};
vm.edit_member_role = function(){
if(vm.current_roles_id == vm.current_edit_member.roles_id){
if((vm.teacher == vm.tmpteacher)&& (vm.assistant == vm.tmpassistant)&&(vm.student == vm.tmpstudent)){
vm.alertService.showMessage('提示', "该用户当前已是该角色");
return;
}
if((vm.teacher == false)&& (vm.assistant == false)&&(vm.student == false)){
vm.alertService.showMessage('提示', "请至少选择一种角色");
return;
}
$http.post(config.apiUrl+'courses/edit_member_role', {
token: auth.token(),
id: course_id,
user_id:vm.current_edit_member.user.id,
role_id:vm.current_edit_member.roles_id
teacher_flag:vm.teacher,
assistant_flag:vm.assistant,
student_flag:vm.student
}).then(function(response){
if(response.data.status!=0){
vm.alertService.showMessage('提示', response.data.message);
} else {
vm.alertService.showMessage('提示', '修改角色成功', function(){
// window.history.back();
$location.path("/class").search({id: course_id,tag:1});
});
}
});
};
vm.selectRole = function(role_id){
vm.current_edit_member.roles_id = role_id;
if (role_id == 7){
if(!vm.teacher){
vm.assistant = !vm.assistant;
}
}
else if (role_id == 9){
if(!vm.assistant){
vm.teacher = !vm.teacher;
}
}
else if (role_id == 10){
vm.student = !vm.student;
}
}
}] );

View File

@ -23,6 +23,7 @@ app.controller('EditProjectMemberController', ['$scope', '$http', 'auth', 'confi
project_id = response.data.project_id;
user_id = response.data.user_id;
vm.current_edit_member = response.data.member_info;
vm.current_edit_member.roles_id = vm.current_edit_member.roles_id[0];
vm.current_roles_id = vm.current_edit_member.roles_id;
}
});
@ -31,13 +32,10 @@ app.controller('EditProjectMemberController', ['$scope', '$http', 'auth', 'confi
console.log(vm.current_edit_member);
vm.cancel = function(){
vm.alertService.showMessage('提示', '您确定不对角色进行变更吗?', function(){
// rms.save("project_master_members",[]);
// rms.save("project_develop_members",[]);
// rms.save("project_report_members",[]);
window.history.back();
// $location.path("/project").search({id: project_id});
});
// vm.alertService.showMessage('提示', '您确定不对角色进行变更吗?', function(){
// window.history.back();
// });
window.history.back();
};
vm.edit_member_role = function(){
@ -63,6 +61,8 @@ app.controller('EditProjectMemberController', ['$scope', '$http', 'auth', 'confi
rms.save("project_master_members",[]);
rms.save("project_develop_members",[]);
rms.save("project_report_members",[]);
rms.save("review_master_members",[]);
rms.save("review_develop_members",[]);
rms.save('tab_num',null);
// window.history.back();
$location.path("/project").search({id: project_id,tag:1});
@ -70,7 +70,6 @@ app.controller('EditProjectMemberController', ['$scope', '$http', 'auth', 'confi
}
});
};
vm.selectRole = function(role_id){

View File

@ -3,7 +3,7 @@
*/
app.controller('InviteCodeController', ['$scope','$http', '$routeParams','config','auth', function($scope, $http, $routeParams, config, auth){
app.controller('InviteCodeController', ['$scope','$http', '$routeParams','config','auth','wx','common', function($scope, $http, $routeParams, config, auth, wx,common){
var vm = $scope;
vm.course = {};
@ -12,6 +12,40 @@ app.controller('InviteCodeController', ['$scope','$http', '$routeParams','config
function(response){
console.log(response.data);
vm.course = response.data.data;
var desc = "班级邀请:"+vm.course.name+" 班级";
common.wxConfig("",desc,"");
// wx.ready(function(){
// wx.onMenuShareTimeline({
// title: 'Trustie创新实践平台', // 分享标题
//// link: 'http://www.trustie.net/', // 分享链接
// imgUrl: 'http://www.trustie.net/images/logo2.png', // 分享图标
// success: function () {
// console.log("share successed.");
// },
// cancel: function () {
// console.log("share canceled.");
// }
// });
//
// wx.onMenuShareAppMessage({
// title: 'Trustie创新实践平台', // 分享标题
// desc: desc, // 分享描述
//// link: '', // 分享链接
//// imgUrl: '', // 分享图标
// imgUrl: 'http://www.trustie.net/images/logo2.png', // 分享图标
//// type: '', // 分享类型,music、video或link不填默认为link
//// dataUrl: '', // 如果type是music或video则要提供数据链接默认为空
// success: function () {
// // 用户确认分享后执行的回调函数
// },
// cancel: function () {
// // 用户取消分享后执行的回调函数
// }
// });
// });
}
);

View File

@ -0,0 +1,80 @@
app.controller('JoinClassController', ['$scope', '$http', 'auth', 'config', 'alertService','$location','$routeParams','rms','wx', function($scope, $http, auth, config, alertService, $location,$routeParams, rms,wx){
var vm = $scope;
// vm.current_edit_member = rms.get('current_edit_member');
vm.current_edit_member = null;
var tag = $routeParams.tag;
vm.alertService = alertService.create();
vm.invite_code = "";
vm.teacher = false; //教师
vm.assistant = false; //教辅
vm.student = false; //学生.
vm.cancel = function(){
// vm.alertService.showMessage('提示', '您确定不对角色进行变更吗?', function(){
// window.history.back();
// });
if(tag){
window.history.back();
}
else{
wx.closeWindow();
}
};
vm.joinClass = function(){
if((vm.teacher == false)&& (vm.assistant == false)&&(vm.student == false)){
vm.alertService.showMessage('提示', "请至少选择一个角色");
return;
}
if(vm.invite_code.length == 0)
{
vm.alertService.showMessage('提示', '请输入5位邀请码');
return;
}
if(vm.invite_code.length != 5)
{
vm.alertService.showMessage('提示', '邀请码格式不正确');
return;
}
$http.post(config.apiUrl+'courses/join_class', {
token: auth.token(),
invite_code: vm.invite_code,
teacher_flag:vm.teacher,
assistant_flag:vm.assistant,
student_flag:vm.student
}).then(function(response){
if(response.data.status == 0){
vm.alertService.showMessage('提示', response.data.message,function(){
$location.path("/class_list");
});
} else {
vm.alertService.showMessage('提示', response.data.message);
}
});
};
vm.selectRole = function(role_id){
if (role_id == 7){
if(!vm.teacher){
vm.assistant = !vm.assistant;
}
}
else if (role_id == 9){
if(!vm.assistant){
vm.teacher = !vm.teacher;
}
}
else if (role_id == 10){
vm.student = !vm.student;
}
}
}] );

View File

@ -0,0 +1,60 @@
app.controller('JoinProjectController', ['$scope', '$http', 'auth', 'config', 'alertService','$location','$routeParams','rms','wx', function($scope, $http, auth, config, alertService, $location,$routeParams, rms,wx){
var vm = $scope;
// vm.current_edit_member = rms.get('current_edit_member');
vm.role_id = 0;
vm.alertService = alertService.create();
vm.invite_code = "";
var tag = $routeParams.tag;
vm.cancel = function(){
if(tag){
window.history.back();
}
else{
wx.closeWindow();
}
};
vm.join_project = function(){
if(vm.role_id == 0){
vm.alertService.showMessage('提示', "请至少选择一个角色");
return;
}
if(vm.invite_code.length == 0)
{
vm.alertService.showMessage('提示', '请输入6位邀请码');
return;
}
if(vm.invite_code.length != 6)
{
vm.alertService.showMessage('提示', '邀请码格式不正确');
return;
}
$http.post(config.apiUrl+'projects/join_project', {
token: auth.token(),
invite_code: vm.invite_code,
role_id:vm.role_id
}).then(function(response){
if(response.data.status == 0){
vm.alertService.showMessage('提示', response.data.message,function(){
$location.path("/project_list");
});
} else {
vm.alertService.showMessage('提示', response.data.message);
}
});
};
vm.selectRole = function(role_id){
vm.role_id = role_id;
}
}] );

View File

@ -1,5 +1,11 @@
app.controller('LoginController', ['$scope', '$http', '$location', '$routeParams', 'alertService', 'config','auth','session',
function ($scope, $http, $location, $routeParams, alertService, config, auth,session) {
app.controller('LoginController', ['$scope', '$http', '$location', '$routeParams', 'alertService', 'config','auth','session','wx',
function ($scope, $http, $location, $routeParams, alertService, config, auth,session, wx) {
// 登录页不用显示菜音
wx.ready(function(){
wx.hideOptionMenu();
})
if(auth.get_bind().then(function(){
$location.path("/activities");
}));
@ -33,8 +39,7 @@ app.controller('LoginController', ['$scope', '$http', '$location', '$routeParams
vm.loginFailed = (response.data.status != 0);
if (!$scope.loginFailed) { //绑定成功
vm.alertService.showMessage('提示', response.data.message, function(){
// $location.path("/activities");
window.WeixinJSBridge.call('closeWindow');
wx.closeWindow();
});
} else {
vm.alertService.showMessage('出错了', response.data.message);

View File

@ -19,16 +19,31 @@ app.controller('ProjectController', ['$scope', 'config','$http','$timeout', 'aut
vm.project_develop_members = rms.get("project_develop_members") || [];
vm.project_report_members = rms.get("project_report_members") || [];
// vm.review_master_members = rms.get("review_master_members") || [];
// vm.review_develop_members = rms.get("review_master_members") || [];
vm.review_master_members = rms.get("review_master_members") || [];
vm.review_develop_members = rms.get("review_develop_members") || [];
// vm.project_members_has_more = rms.get("project_members_has_more");
vm.alertService = alertService.create();
//跳入邀请界面
vm.invite = function(){
vm.alertService.showMessage('提示', "该功能将在近日开放,敬请期待!");
// vm.alertService.showMessage('提示', "该功能将在近日开放,敬请期待!");
rms.save('project_activities_page',vm.project_activities_page);
rms.save("project_activities",vm.project_activities);
rms.save("project_has_more",vm.project_has_more);
rms.save("project",vm.project);
rms.save("project_master_members",vm.project_master_members);
rms.save("project_develop_members",vm.project_develop_members);
rms.save("project_report_members",vm.project_report_members);
rms.save("review_master_members",vm.review_master_members);
rms.save("review_develop_members",vm.review_develop_members);
// $location.path("/project_invite_code").search({id: projectid});
$location.path("/project_invite_code").search({id: projectid});
};
//获取项目动态
@ -82,6 +97,8 @@ app.controller('ProjectController', ['$scope', 'config','$http','$timeout', 'aut
vm.project_develop_members = response.data.develop_members;
vm.project_report_members = response.data.report_members;
vm.review_master_members = response.data.review_master_members;
vm.review_develop_members = response.data.review_develop_members;
}
else{
vm.alertService.showMessage('提示', response.data.message);
@ -141,9 +158,11 @@ app.controller('ProjectController', ['$scope', 'config','$http','$timeout', 'aut
if(tag){
vm.tab(2);
tag = null;
vm.currentTab = 2;
}
else{
vm.tab(1);
vm.currentTab = 1;
}
}
else{
@ -154,8 +173,6 @@ app.controller('ProjectController', ['$scope', 'config','$http','$timeout', 'aut
}
}
);
vm.currentTab = 1;
vm.tab(vm.currentTab);
} else {
$timeout(function(){
window.scrollTo(0, rms.get("yoffset"));
@ -197,8 +214,23 @@ app.controller('ProjectController', ['$scope', 'config','$http','$timeout', 'aut
rms.save("project_master_members",vm.project_master_members);
rms.save("project_develop_members",vm.project_develop_members);
rms.save("project_report_members",vm.project_report_members);
rms.save("review_master_members",vm.review_master_members);
rms.save("review_develop_members",vm.review_develop_members);
$location.path("/edit_project_member").search({id: projectid,user_id: data.user.id});
};
vm.review = function(user){
rms.save('current_review_member', user);
rms.save('current_project', vm.project);
rms.save("project",vm.project);
rms.save("project_master_members",vm.project_master_members);
rms.save("project_develop_members",vm.project_develop_members);
rms.save("project_report_members",vm.project_report_members);
rms.save("review_master_members",vm.review_master_members);
rms.save("review_develop_members",vm.review_develop_members);
$location.path("/review_project_member").search({id: projectid,user_id: user.id});
}
}]);

View File

@ -3,7 +3,7 @@
*/
app.controller('ProjectInviteCodeController', ['$scope','$http', '$routeParams','config','auth', function($scope, $http, $routeParams, config, auth){
app.controller('ProjectInviteCodeController', ['$scope','$http', '$routeParams','config','auth','wx','common', function($scope, $http, $routeParams, config, auth,wx,common){
var vm = $scope;
vm.project = {};
@ -12,23 +12,43 @@ app.controller('ProjectInviteCodeController', ['$scope','$http', '$routeParams',
function(response){
console.log(response.data);
vm.project = response.data.data;
var desc = "项目邀请:"+vm.project.name+" 项目";
common.wxConfig("",desc,"");
// wx.ready(function(){
// wx.onMenuShareTimeline({
// title: 'Trustie创新实践平台', // 分享标题
//// link: 'http://www.trustie.net/', // 分享链接
// imgUrl: 'http://www.trustie.net/images/logo2.png', // 分享图标
// success: function () {
// console.log("share successed.");
// },
// cancel: function () {
// console.log("share canceled.");
// }
// });
//
// wx.onMenuShareAppMessage({
// title: 'Trustie创新实践平台', // 分享标题
// desc: desc, // 分享描述
//// link: '', // 分享链接
//// imgUrl: '', // 分享图标
// imgUrl: 'http://www.trustie.net/images/logo2.png', // 分享图标
//// type: '', // 分享类型,music、video或link不填默认为link
//// dataUrl: '', // 如果type是music或video则要提供数据链接默认为空
// success: function () {
// // 用户确认分享后执行的回调函数
// },
// cancel: function () {
// // 用户取消分享后执行的回调函数
// }
// });
// });
}
);
vm.share = function(){
window.WeixinJSBridge.invoke('sendAppMessage',{
'appid': 'wxf694495398c7d470', // 公众号appID
'type': 'link', // 非必填music,vido或link,默认为link。
'data_url': '', // 非必填,连接地址,如音乐的mp3数据地址,供内置播放器使用
'img_url': 'http://pnewsapp.tc.qq.com/newsapp_bt/0/9963967/640', // 缩略图地址
'img_height':370, // 缩略图高度
'img_width':550, // 缩略图宽度
'link':'http://view.inews.qq.com/a/WXN2013101101385701', // 链接地址
'desc':'desc', // 描述
'title':'title' // 标题
},function(res){
//alert(res.err_msg);
});
}
}]);

View File

@ -17,6 +17,10 @@ app.controller('ProjectListController', ['$scope', 'config', 'auth', '$http', '$
function (response) {
console.log(response.data);
vm.projects = response.data.data;
rms.save('projects', vm.projects);
}
);
@ -32,9 +36,12 @@ app.controller('ProjectListController', ['$scope', 'config', 'auth', '$http', '$
rms.save("project_activities",[]);
rms.save("project_has_more",false);
rms.save("project",null);
rms.save('project_members_page',0);
rms.save("project_members",[]);
rms.save("project_members_has_more",false);
rms.save("project_master_members",[]);
rms.save("project_develop_members",[]);
rms.save("project_report_members",[]);
rms.save("review_master_members",[]);
rms.save("review_develop_members",[]);
rms.save('tab_num',null);
console.log(project_id);
$location.path("/project").search({id: project_id});
@ -45,7 +52,7 @@ app.controller('ProjectListController', ['$scope', 'config', 'auth', '$http', '$
};
vm.joinProject = function () {
vm.alertService_1.showMessage('提示', "该功能将在近日开放,敬请期待!");
// vm.alertService_1.showMessage('提示', "该功能将在近日开放,敬请期待!");
// vm.alertService_3.showMessage('提示', '请输入6位项目邀请码(不区分大小写)', function(){
// if (vm.alertService_3.invite && vm.alertService_3.invite.length == 6) {
@ -68,6 +75,7 @@ app.controller('ProjectListController', ['$scope', 'config', 'auth', '$http', '$
// }
// }
// });
$location.path("/join_project").search({tag: 1});
};
vm.onSetting = function (project) {

View File

@ -0,0 +1,68 @@
app.controller('ReviewClassMemberController', ['$scope', '$http', 'auth', 'config', 'alertService','$location','$routeParams','rms', function($scope, $http, auth, config, alertService, $location,$routeParams, rms){
var vm = $scope;
// vm.current_edit_member = rms.get('current_edit_member');
vm.current_review_member = rms.get('current_review_member');
vm.current_course = rms.get('current_course');
vm.alertService = alertService.create();
var course_id = $routeParams.id;
var user_id = $routeParams.user_id;
if(!vm.current_course){
$http.get(config.apiUrl+ 'courses/'+course_id+"?token="+auth.token()).then(
function(response) {
console.log(response.data);
if (response.data.status == 0){
vm.current_course = response.data.data;
console.log("courses");
console.log(response.data.data);
}
else{
vm.alertService.showMessage('提示', response.data.message);
}
}
);
}
if(!vm.current_review_member){
$http.post(config.apiUrl+'courses/review_member_info', {
token: auth.token(),
course_id: course_id,
user_id:user_id
}).then(function(response){
if(response.data.status!=0){
vm.alertService.showMessage('提示', response.data.message);
} else {
vm.current_review_member = response.data.data;
console.log("review_member_info");
console.log(response.data.data);
}
});
}
vm.deal = function(result){
$http.post(config.apiUrl+'courses/deal_join_apply', {
token: auth.token(),
course_id: course_id,
user_id:user_id,
type:result
}).then(function(response) {
if (response.data.status == 0) {
vm.alertService.showMessage('提示', response.data.message, function () {
$location.path("/class").search({id: course_id,tag:1});
});
}
else{
vm.alertService.showMessage('提示', response.data.message);
}
});
};
}] );

View File

@ -0,0 +1,72 @@
app.controller('ReviewProjectMemberController', ['$scope', '$http', 'auth', 'config', 'alertService','$location','$routeParams','rms', function($scope, $http, auth, config, alertService, $location,$routeParams, rms){
var vm = $scope;
// vm.current_edit_member = rms.get('current_edit_member');
vm.current_review_member = rms.get('current_review_member');
vm.current_project = rms.get('current_project');
vm.alertService = alertService.create();
var project_id = $routeParams.id;
var user_id = $routeParams.user_id;
if(!vm.current_project){
$http.get(config.apiUrl+ 'projects/'+project_id+"?token="+auth.token()).then(
function(response) {
console.log(response.data);
if (response.data.status == 0){
vm.current_project = response.data.data;
console.log("projects");
console.log(response.data.data);
}
else{
vm.alertService.showMessage('提示', response.data.message);
}
}
);
}
if(!vm.current_review_member){
$http.post(config.apiUrl+'projects/review_member_info', {
token: auth.token(),
project_id: project_id,
user_id:user_id
}).then(function(response){
if(response.data.status!=0){
vm.alertService.showMessage('提示', response.data.message);
} else {
vm.current_review_member = response.data.data;
console.log("review_member_info");
console.log(response.data.data);
}
});
}
vm.deal = function(result){
$http.post(config.apiUrl+'projects/deal_join_apply', {
token: auth.token(),
project_id: project_id,
user_id:user_id,
type:result
}).then(function(response) {
if (response.data.status == 0) {
vm.alertService.showMessage('提示', response.data.message, function () {
rms.save("project_master_members",[]);
rms.save("project_develop_members",[]);
rms.save("project_report_members",[]);
rms.save("review_master_members",[]);
rms.save("review_develop_members",[]);
rms.save("tab_num",null);
$location.path("/project").search({id: project_id,tag:1});
});
}
else{
vm.alertService.showMessage('提示', response.data.message);
}
});
};
}] );

View File

@ -1,25 +1,25 @@
/**
* Created by Tim on 7/22/16.
*/
//app.directive('ellipsisShow',["$timeout",function(timer){
// return{
// restrict: 'A',
// scope: {},
// link: function(scope, element){
// timer(function() {
// var textSplit = element.text().split(" ");
// var newContent = [];
// element.text("");
// for (var i = 0; i < textSplit.length; i++) {
// newContent = newContent + " " + textSplit[i];
// element.text(newContent);
// if(element[0].scrollHeight >= 100){
// newContent = newContent + " " + textSplit[i+1] + " " + textSplit[i+2] + " " + textSplit[i+3] + " " + textSplit[i+4] + "...";
// element.text(newContent);
// break;
// }
// }
// });
// }
// }
//}]);
app.directive('ellipsisShow',["$timeout",function(timer){
return{
restrict: 'A',
scope: {},
link: function(scope, element){
timer(function() {
var textSplit = element.text().split("");
var newContent = [];
element.text("");
for (var i = 0; i < textSplit.length; i++) {
newContent = newContent + textSplit[i];
element.text(newContent);
if(element[0].scrollHeight >= 100){
newContent = newContent + textSplit[i+1] + textSplit[i+2] + textSplit[i+3] + textSplit[i+4] + textSplit[i+5] + textSplit[i+6] + textSplit[i+7] + textSplit[i+8] + textSplit[i+9] + textSplit[i+10] + "...";
element.text(newContent);
break;
}
}
});
}
}
}]);

View File

@ -30,6 +30,10 @@ app.factory('alertService', function(){
}
});
app.factory('wx', ['$window', function($window){
var wechat = $window.wx;
return wechat;
}]);
app.factory('auth', ['$http','$routeParams', '$q', 'session', 'config',function($http,$routeParams, $q, session,config){
//是否已经绑定
@ -89,7 +93,7 @@ app.factory('rms', function(){
return {save: save, get: get};
});
app.factory('common', ['$http', 'auth', '$routeParams','rms','config', function($http, auth, $routeParams,rms,config){
app.factory('common', ['$http', 'auth', '$routeParams','rms','config','wx', function($http, auth, $routeParams,rms,config,wx){
var addCommonReply = function(id, type, data, cb){
if(!data.comment || data.comment.length<=0){
@ -196,6 +200,47 @@ app.factory('common', ['$http', 'auth', '$routeParams','rms','config', function(
args.scope.formData = {comment: ''};
var loadData = function(id,replytype,page){
loadCommonData(id, args.type,replytype,page).then(function successCallback(response) {
console.log(response.data);
//--------------分享内容定制-------------
var tmptile = "分享动态";
var imgUrl = "";
if(response.data.data.title){
tmptile = response.data.data.title;
}
var tmpname = "匿名用户";
if(response.data.data.user){
tmpname = response.data.data.user.realname;
imgUrl = window.g_localhost+response.data.data.user.img_url;
}
if(response.data.data.author){
tmpname = response.data.data.author.realname;
imgUrl = window.g_localhost+response.data.data.author.img_url;
}
var desc = ""
if(response.data.data.content){
desc = response.data.data.content.replace(/<[^>]+>/g,"").replace(/\s*/g,"").replace(/&nbsp;/g,"");
}
if(response.data.data.description){
desc = response.data.data.description.replace(/<[^>]+>/g,"").replace(/\s*/g,"").replace(/&nbsp;/g,"");
}
if(desc.length > 30){
desc = desc.substring(0,30)+"...";
}
var title = tmpname+""+tmptile;
console.log("desc = "+desc);
console.log("imgUrl= "+imgUrl);
wxConfig(title,desc,imgUrl);
//--------------分享内容定制-------------
args.loadCallback(response.data);
}, function errorCallback(response) {
});
@ -298,7 +343,52 @@ app.factory('common', ['$http', 'auth', '$routeParams','rms','config', function(
args.scope.commentreply_path = config.rootPath+ 'templates/comment_reply.html';
}
};
return {init: init, addCommonReply: addCommonReply, loadCommonData: loadCommonData, addCommonPraise: addCommonPraise, decreaseCommonPraise: decreaseCommonPraise};
var wxConfig = function(title,desc,imgUrl){
if(title == null || title == ""){
title = 'Trustie创新实践平台';
}
if(desc == null || desc == ""){
desc = 'Trustie创新实践平台';
}
if(imgUrl == null || imgUrl == ""){
imgUrl = 'http://www.trustie.net/images/logo2.png';
}
wx.ready(function(){
wx.onMenuShareTimeline({
title: title, // 分享标题
// link: 'http://www.trustie.net/', // 分享链接
imgUrl: imgUrl, // 分享图标
success: function () {
console.log("share successed.");
},
cancel: function () {
console.log("share canceled.");
}
});
wx.onMenuShareAppMessage({
title: title, // 分享标题
desc: desc, // 分享描述
// link: '', // 分享链接
// imgUrl: '', // 分享图标
imgUrl: imgUrl, // 分享图标
// type: '', // 分享类型,music、video或link不填默认为link
// dataUrl: '', // 如果type是music或video则要提供数据链接默认为空
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
};
return {init: init, addCommonReply: addCommonReply, loadCommonData: loadCommonData, addCommonPraise: addCommonPraise, decreaseCommonPraise: decreaseCommonPraise, wxConfig: wxConfig};
}]);

View File

@ -38,11 +38,15 @@ app.config(['$routeProvider',"$httpProvider", "$locationProvider",'config', func
.when('/myresource', makeRoute('myresource.html', 'MyResourceController'))
.when('/invite_code', {templateUrl: rootPath + 'invite_code.html', controller: 'InviteCodeController'})
.when('/send_class_list', makeRoute('send_class_list.html', 'SendClassListController'))
.when('/join_class', makeRoute('join_class.html', 'JoinClassController'))
.when('/review_class_member', makeRoute('review_class_member.html', 'ReviewClassMemberController'))
.when('/project_list', makeRoute('project_list.html', 'ProjectListController'))
.when('/project', makeRoute('project.html', 'ProjectController'))
.when('/edit_project_member', makeRoute('edit_project_member.html', 'EditProjectMemberController'))
.when('/new_project', makeRoute('new_project.html', 'NewProjectController'))
.when('/project_invite_code', {templateUrl: rootPath + 'project_invite_code.html', controller: 'ProjectInviteCodeController'})
.when('/join_project', makeRoute('join_project.html', 'JoinProjectController'))
.when('/review_project_member', makeRoute('review_project_member.html', 'ReviewProjectMemberController'))
.otherwise({
redirectTo: '/activites'
});

View File

@ -1,245 +1,250 @@
@charset "utf-8";
/* CSS Document */
/*基本样式*/
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体","Helvetica Neue", Helvetica, Arial, sans-serif;}
body, ul, h1,h2,h3,h4,h5,p,pre,input {padding:0px; margin:0px;}
body{background-color: #efeff4;}
ul li {list-style:none;}
img {max-width:100%;}
blockquote {border:1px solid #d4d4d4; padding: 0.6em; margin: 5px 0.4em 5px 1.4em; border-radius: 4px; font-family: "Microsoft YaHei"; background-size: 100% 100%;}
.text-control {word-break:normal; word-wrap:break-word;}
.f12 {font-size:12px;}
.f13 {font-size:13px;}
.f14 {font-size:14px;}
.f15 {font-size:15px;}
.f16 {font-size:16px;}
.fb {font-weight:bold;}
.mt2 {margin-top:2px;}
.mt3 {margin-top:3px;}
.mt4 {margin-top:4px;}
.mt5 {margin-top:5px;}
.mt10 {margin-top:10px;}
.mt11 {margin-top:11px;}
.mt12 {margin-top:12px;}
.mt15 {margin-top:15px;}
.mt30 {margin-top:30px;}
.mt70 {margin-top:70px;}
.mb5 {margin-bottom:5px;}
.mb10 {margin-bottom:10px;}
.mb15 {margin-bottom:15px;}
.mb20 {margin-bottom:20px;}
.mb50 {margin-bottom:50px;}
.ml5 {margin-left:5px;}
.ml10 {margin-left:10px;}
.ml40 {margin-left:40px;}
.mr5 {margin-right:5px;}
.mr10 {margin-right:10px;}
.ml15 {margin-left:15px;}
.ml35 {margin-left:35px;}
.mr15 {margin-right:15px;}
.mr20 {margin-right:20px;}
.ml25 {margin-left:25px;}
.mr25 {margin-right:25px;}
.ml55 {margin-left:55px;}
.mr55 {margin-right:55px;}
.c-red {color:#e81a1a;}
.c-blue {color:#269ac9;}
.c-grey {color:#9a9a9a !important;}
.c-grey2 {color:#707070;}
.c-grey3 {color:#555555;}
.c-grey4 {color:#888888;}
.c-grey5 {color:#aaaaaa;}
.c-grey6 {color:#777777;}
.c-blue {color:#3b94d6;}
.c-white {color:#ffffff;}
.c-black {color:#333}
a {color:#707070;}
a.c-grey {color:#707070;}
a.c-grey2 {color:#9a9a9a;}
a.c-grey3 {color:#353535;}
a.c-green {color:#0bb20c;}
a:link,a:visited{text-decoration:none;}
a:hover,a:active{cursor:pointer;}
a.link-blue {color:#269ac9;}
a.link-blue2 {color:#3b94d6;}
a.underline {text-decoration:underline;}
.border-radius {border-radius:5px;}
.w36 {width:36px;}
.max-width-60 {max-width:60px;}
.max-width-130 {max-width:130px;}
.hidden {overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}
.inline-block {display:inline-block;}
.dis {display:block;}
.undis {display:none;}
.text-nowrap {white-space:nowrap;}
.v-top {vertical-align:top;}
.tac {text-align:center;}
.block-center {margin-left:auto; margin-right:auto; display:block;}
/*背景色*/
.bg-grey {background-color:#c1c1c1 !important;}
.bg-blue {background-color:#3b94d6;}
/*按钮样式*/
.btn1 {width:100%; height:40px; line-height:40px; vertical-align:middle; text-align:center; color:#fff; display:block; border-radius:5px;}
.bg-blue:not(.btn-disabled):active {background-color:#2780c2;}
.btn-disabled {background-color:#ccc !important;}
.btn2 {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; margin:18px auto 20px auto; border-radius:50px; display:block;}
.btn3 {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; border-radius:50px; display:block;}
.fixed-bottom-btn {position:fixed; bottom:5px; left:50%; transform:translate(-50%,0);}
/*tab*/
.tab-wrap {position:relative; width:100%; line-height:38px; display:-webkit-box; display:-moz-box; display:-ms-flexbox; display:-webkit-flex; display:flex; font-size:13px; background-color:#fff;}
.tab-wrap a {position:relative; display:block; -webkit-box-flex:1; -moz-box-flex:1; -ms-flex:1; flex:1;}
.tab-wrap a:first-child:after {display:none;}
.tab-wrap a:after {content:" "; position:absolute; left:0; top:0; width:1px; height:100%; border-left:1px solid #ccc; color:#707070;}
.weixin-tab {text-align:center; border-bottom:1px solid #ccc;}
/*bottom-tab*/
.bottom-tab-wrap {position:fixed; width:100%; bottom:0; line-height:38px; display:-webkit-box; display:-moz-box; display:-ms-flexbox; display:-webkit-flex; display:flex; font-size:13px; background-color:#fff;}
.bottom-tab-wrap a {display:block; -webkit-box-flex:1; -moz-box-flex:1; -ms-flex:1; flex:1; position:relative;}
.bottom-tab-wrap a:after {content:" "; position:absolute; left:0; top:0; width:1px; height:100%; border-left:1px solid #ccc; color:#707070;}
/*动态样式*/
.post-container {width:100%;}
.post-wrapper {width:100%; background-color:#ffffff; margin:10px auto;}
.post-main {padding:10px 15px; color:#9a9a9a;}
.post-avatar {width:30px; height:30px;}
.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;}
.post-content {width:100%; font-size:14px; line-height:20px; height:100px; overflow:hidden; word-break:normal; word-wrap:break-word; text-align:justify;}
.post-all-content a {color:#136ec2;}
.post-interactive {width:100%; height:35px; line-height:35px; vertical-align:middle; border-top:1px solid #e6e6e6; background-color:#f8f9fb;}
.post-interactive-column,
.post-interactive-reply,
.post-interactive-praise {width:50%; text-align:center; float:left; font-size:13px;}
.more-wrap {width:100%;}
.more-events {width:100%; font-size:13px; text-align:center; margin:0 auto; padding: 5px 0; border-top:1px solid #e6e6e6; border-bottom:1px solid #e6e6e6; border-radius:3px; background-color:#f8f9fb; }
.border-bottom {border-bottom:1px solid #e6e6e6;}
.post-reply-wrap {width:100%;}
.post-reply-wrap:first-child {border-top:1px solid #ccc;}
.post-input-wrap {width:100%; position:fixed; bottom:0; background-color:#fff;}
.post-input-wrap2 {width:100%;}
.post-reply-row {margin:10px 15px; color:#9a9a9a; background-color:#fff; border-bottom:1px solid #f0f0f0;}
.post-reply-avatar {width:45px; height:30px; text-align:center; margin-right:10px;}
.post-reply-user {font-size:13px; text-align:left; margin-bottom:10px;}
.post-reply-content {font-size:13px; word-break:break-all; word-wrap:break-word; overflow:hidden; text-align:justify;}
.post-reply-content img {max-width:100%;}
.post-reply-content a {color:#136ec2;}
.post-reply-date, .post-reply-trigger {font-size:13px;}
.post-input-container {position:relative; padding-right:70px;}
.copy-input-container {position:relative; padding-right:70px;}
.copy-input {width:100%; height:18px; line-height:18px; padding:5px; vertical-align: middle; font-size:12px; border-radius:3px; position:absolute; left:-999em;}
.post-reply-input {width:100%; height:18px; max-height:54px; line-height:18px; vertical-align: middle; font-size:13px; border:1px solid #e6e6e6; outline:none; padding:5px; margin:0; border-radius:3px; overflow-y:auto; resize:none; background-color:#f0eff4;}
.post-reply-submit {position:absolute; font-size:13px; height:30px; line-height:30px; vertical-align:middle; padding:0 8px; color:#fff; background-color:#269ac9; outline:none; border:none; top:0; right:0;}
.reply-icon {background:url(/images/wechat/icon_list.gif) -150px -155px no-repeat; width:20px; height:20px; display:inline-block; vertical-align:middle;}
.praise-icon {background:url(/images/wechat/icon_list.gif) -36px -88px no-repeat; width:20px; height:20px; display:inline-block; vertical-align:middle;}
.praised-icon {background:url(/images/wechat/icon_list.gif) -152px -86px no-repeat; width:20px; height:20px; display:inline-block; vertical-align:middle;}
.num-block {display:inline-block; vertical-align:top;}
.post-op-banner {height:20px; line-height:20px; vertical-align:middle;}
/*20160628动态新样式*/
.post-dynamic-author {width:50%; height:30px; line-height:30px; font-size:14px; color:#5b5b5b; vertical-align:middle;}
.post-dynamic-time {height:30px; line-height:30px; vertical-align:middle;}
.post-dynamic-title {font-size:15px;}
.post-dynamic-from {width:50%; font-size:13px;}
.post-box-shadow {box-shadow: 0px 2px 8px rgba(146, 153, 169, 0.5);}
.post-reply-author {width:50%; height:20px; line-height:20px; font-size:12px; color:#5d5d5d; vertical-align:middle;}
.post-reply-time {height:20px; line-height:20px; vertical-align:middle;}
/* loading 弹框*/
.loading-bg {position:fixed; width:100%; height:100%; left:0; top:0; z-index:99; background:rgba(206, 206, 206, 0.3); overflow:hidden;}
.loading-box {position:absolute; top:50%; background:rgba(240,240,240, 0.5); width:160px; height:72px; left:50%; margin-top:-36px; margin-left:-80px; text-align:center;}
.loading-box img {margin-top: 3px; text-align: center;}
.loading-box span {display: block; font-size:12px;}
/*帖子锁定样式*/
.locked_btn_cir {background: url("/images/wechat/locked.png") 0 0 no-repeat; cursor: default;}
/*20150612加入班级样式*/
.add-class-box {position:fixed; width:80%; max-width:300px; min-width:240px; font-size:15px; color:#444; background-color:#fff; box-shadow: 0px 2px 8px rgba(146, 153, 169, 0.5); border-radius:5px; top:50%; left:50%; transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%); -moz-transform: translate(-50%,-50%); -webkit-transform: translate(-50%,-50%); -o-transform: translate(-50%,-50%);}
.add-class-tip {padding-top:1.2em; padding-bottom:.5em; font-weight:400;}
.class-number-input {width:80%; max-width:240px; height:28px; border:1px solid #ccc; padding-left:5px; margin:0 auto; display:block;}
.cancel-btn {width:49%; height:37px; line-height:37px; text-align:center; vertical-align:middle; border-top:1px solid #ccc;}
.submit-btn {width:49%; height:37px; line-height:37px; text-align:center; vertical-align:middle; border-top:1px solid #ccc;}
.slice {width:2%; text-align:center; border-top:1px solid #ccc;}
.slice-line {width:1px; height:37px; margin:auto; background:#ccc;}
/*20160613邀请码样式*/
.qr-code-wrap {width:100%; padding:40px 0; background-color:#3b94d6;}
.qr-code-box {width:225px; background-color:#fff; border-radius:3px; margin:0 auto;}
.share-class-name {font-size:18px; color:#3b3b3b; text-align:center; padding:12px; border-bottom:1px solid #cccccc;}
.qr-img-wrap {width:100%; border-bottom:1px dashed #ccc;}
.qr-code-img {margin:36px auto; display:block;}
.invitation-code-wrap {text-align:center; font-size:18px; color:#3b3b3b; padding:16px;}
.share-code-wrap {width:100%; background-color:#efeff4;}
.share-code-btn, .finish-btn {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; background-color:#ff7239; margin:18px auto 20px auto; border-radius:50px; display:block;}
.share-code-instruction {max-width:228px; font-size:12px; color:#666; line-height:20px; margin:0 auto;}
/*20160613班级详情*/
.class-detail-name, .blue-title {width:100%; height:45px; line-height:45px; vertical-align:middle; background-color:#3b94d6; color:#fff; font-size:18px; text-align:center;}
.blue-title-sub {position:absolute; right:10px;}
.slice2 {width:2%; text-align:center; background-color:#fff; border-bottom:1px solid #ccc;}
.slice3 {width:1%; height:38px; text-align:center; background-color:#fff; border-bottom:1px solid #ccc;}
.slice-line2 {width:1px; height:38px; margin:auto; background:#ccc;}
.class-detail-tab {width:23%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-detail-tab2 {width:32%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-detail-tab3 {width:48%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-tab-active {border-bottom:3px solid #3b94d6;}
.tab-active-arrow {border-width:4px; position:absolute; top:41px; left:50%; transform:translate(-50%,0); border-color:#3b94d6 transparent transparent transparent; border-style:solid dashed dashed dashed;}
.class-search-wrap {padding:8px 12px; position:relative;}
.class-search-inner {padding:0 30px; background-color:#fff;}
.class-search-icon {position:absolute; top:16px; left:16px;}
.class-detail-search {width:100%; height:33px; color:#999; background-color:#fff; border:none; outline:none;}
.border-top {border-top:1px solid #ccc;}
.class-detail-row {width:100%; line-height:18px; padding:10px 0; border-bottom:1px solid #ccc; background-color:#fff;}
.class-member-row {width:100%; line-height:18px; padding:5px 0; border-bottom:1px solid #ccc; background-color:#fff; position:relative;}
.class-test-tip {text-align:center; font-size:13px; color:#444; padding-top:40px;}
.img-circle {border-radius:50% !important;}
.member-banner {height:24px; line-height:24px; text-align:center; vertical-align:middle; background-color:#dfdfdf;}
.resource-width {width:76%;}
.courseware-from-width {max-width:57%;}
.other-from-width {max-width:80%;}
.course-name-width {width:68%;}
/*20160614班级列表*/
.course-diff-row {width:100%; height:28px; line-height:28px; vertical-align:middle; background-color:#fff; border-bottom:1px solid #ccc;}
.course-list-row {width:100%; height:38px; line-height:38px; vertical-align:middle; border-top:1px solid #ccc; border-bottom:1px solid #ccc; background-color:#fff;}
.class-list {width:100%; border-bottom:1px solid #ccc;}
.class-list li {height:40px; line-height:40px; vertical-align:middle; margin:0 25px; border-left:1px solid #ccc; border-bottom:1px solid #ccc; position:relative;}
.class-list-name {max-width:75%; display:inline-block;}
.class-list-dot {position:absolute; top:13px; left:-8px;}
.border-bottom-none {border-bottom:none !important;}
.border-top-none {border-top:none !important;}
.students-amount {height:14px; line-height:14px; vertical-align:middle; padding:2px 5px; background-color:#e6e6e6; border-radius:10px;}
.new-class-btn {font-size:15px; color:#fff; background-color:#3b94d6; padding:10px 40px; border-radius:20px; display:inline-block; margin:0 auto;}
.join-class-btn {font-size:15px; color:#444; background-color:#ccc; padding:10px 40px; border-radius:20px; display:inline-block; margin:0 auto;}
.new-class-input {width:60%; color:#555; height:16px; line-height:16px; vertical-align:middle; border:none; outline:none; padding:8px 0;}
.class-list-setting {position:absolute; top:11px; right:10px;}
.class-setting-wrap {width:38px; height:38px; position:absolute; top:0; right:0;}
/*20160616登录注册*/
.login-wrap {padding:0 10px;}
.input-box-wrap {padding-right:17px;}
.input-box { -webkit-appearance: none; font-size: 15px;width:100%; height:18px; padding: 10px 0px 10px 5px; line-height:18px; border:1px solid #ccc; border-radius:5px;}
.login-op-wrap {height:30px; line-height:30px; vertical-align:middle;}
.login-box{display:inline-block; width:14px; height:14px; line-height:14px; text-align:center; vertical-align:middle; border:1px solid #ccc; background:#fff; border-radius:3px; color:#fff; cursor:pointer;}
.login-box.checked{background:#63c360; border:1px solid #63c360;}
.login-box.checked:after{content:url(/images/wechat/checked.png);}
.forget-psw-wrap {width:60px; margin:0 auto;}
.forget-psw {position:fixed; bottom:10px;}
/*二级回复*/
.mult-reply-container{ border:solid 1px #f3ddb3; background:#fffef4; padding:4px;color:#999;}
.mult-reply-content{ color:#555; font-size:13px;}
.mult-reply-hide{ text-align:center; display:block; font-size:14px; color:#aaa; border-bottom:1px solid #F3DDB3; padding:8px 0;}
.mult-reply-arrow{ color:#aaa; margin-right:10px; font-size:14px; font-weight:bold;}
/*20160729项目说明*/
.project-intro {line-height:2; width:140px; margin-left:auto; margin-right:auto;}
.project-intro li {list-style:disc; margin-left:20px;}
@charset "utf-8";
/* CSS Document */
/*基本样式*/
body,table,input,textarea,select,button { font-family: "微软雅黑","宋体","Helvetica Neue", Helvetica, Arial, sans-serif;}
body, ul, h1,h2,h3,h4,h5,p,pre,input {padding:0px; margin:0px;}
body{background-color: #efeff4;}
ul li {list-style:none;}
img {max-width:100%;}
blockquote {border:1px solid #d4d4d4; padding: 0.6em; margin: 5px 0.4em 5px 1.4em; border-radius: 4px; font-family: "Microsoft YaHei"; background-size: 100% 100%;}
.text-control {word-break:normal; word-wrap:break-word;}
.f12 {font-size:12px;}
.f13 {font-size:13px;}
.f14 {font-size:14px;}
.f15 {font-size:15px;}
.f16 {font-size:16px;}
.fb {font-weight:bold;}
.mt2 {margin-top:2px;}
.mt3 {margin-top:3px;}
.mt4 {margin-top:4px;}
.mt5 {margin-top:5px;}
.mt10 {margin-top:10px;}
.mt11 {margin-top:11px;}
.mt12 {margin-top:12px;}
.mt15 {margin-top:15px;}
.mt30 {margin-top:30px;}
.mt70 {margin-top:70px;}
.mb5 {margin-bottom:5px;}
.mb10 {margin-bottom:10px;}
.mb15 {margin-bottom:15px;}
.mb20 {margin-bottom:20px;}
.mb50 {margin-bottom:50px;}
.ml5 {margin-left:5px;}
.ml10 {margin-left:10px;}
.ml40 {margin-left:40px;}
.mr5 {margin-right:5px;}
.mr10 {margin-right:10px;}
.ml15 {margin-left:15px;}
.ml35 {margin-left:35px;}
.mr15 {margin-right:15px;}
.mr20 {margin-right:20px;}
.ml25 {margin-left:25px;}
.mr25 {margin-right:25px;}
.ml55 {margin-left:55px;}
.mr55 {margin-right:55px;}
.c-red {color:#e81a1a;}
.c-blue {color:#269ac9;}
.c-grey {color:#9a9a9a !important;}
.c-grey2 {color:#707070;}
.c-grey3 {color:#555555;}
.c-grey4 {color:#888888;}
.c-grey5 {color:#aaaaaa;}
.c-grey6 {color:#777777;}
.c-blue {color:#3b94d6;}
.c-white {color:#ffffff;}
.c-black {color:#333}
a {color:#707070;}
a.c-grey {color:#707070;}
a.c-grey2 {color:#9a9a9a;}
a.c-grey3 {color:#353535;}
a.c-green {color:#0bb20c;}
a:link,a:visited{text-decoration:none;}
a:hover,a:active{cursor:pointer;}
a.link-blue {color:#269ac9;}
a.link-blue2 {color:#3b94d6;}
a.underline {text-decoration:underline;}
.border-radius {border-radius:5px;}
.w36 {width:36px;}
.max-width-60 {max-width:60px;}
.max-width-130 {max-width:130px;}
.hidden {overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}
.inline-block {display:inline-block;}
.dis {display:block;}
.undis {display:none;}
.text-nowrap {white-space:nowrap;}
.v-top {vertical-align:top;}
.tac {text-align:center;}
.block-center {margin-left:auto; margin-right:auto; display:block;}
/*背景色*/
.bg-grey {background-color:#c1c1c1 !important;}
.bg-blue {background-color:#3b94d6;}
/*按钮样式*/
.btn1 {width:100%; height:40px; line-height:40px; vertical-align:middle; text-align:center; color:#fff; display:block; border-radius:5px;}
.bg-blue:not(.btn-disabled):active {background-color:#2780c2;}
.btn-disabled {background-color:#ccc !important;}
.btn2 {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; margin:18px auto 20px auto; border-radius:50px; display:block;}
.btn3 {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; border-radius:50px; display:block;}
.fixed-bottom-btn {position:fixed; bottom:5px; left:50%; transform:translate(-50%,0);}
/*tab*/
.tab-wrap {position:relative; width:100%; line-height:38px; display:-webkit-box; display:-moz-box; display:-ms-flexbox; display:-webkit-flex; display:flex; font-size:13px; background-color:#fff;}
.tab-wrap a {position:relative; display:block; -webkit-box-flex:1; -moz-box-flex:1; -ms-flex:1; flex:1;}
.tab-wrap a:first-child:after {display:none;}
.tab-wrap a:after {content:" "; position:absolute; left:0; top:0; width:1px; height:100%; border-left:1px solid #ccc; color:#707070;}
.weixin-tab {text-align:center; border-bottom:1px solid #ccc;}
/*bottom-tab*/
.bottom-tab-wrap {position:fixed; width:100%; bottom:0; line-height:38px; display:-webkit-box; display:-moz-box; display:-ms-flexbox; display:-webkit-flex; display:flex; font-size:13px; background-color:#fff;}
.bottom-tab-wrap a {display:block; -webkit-box-flex:1; -moz-box-flex:1; -ms-flex:1; flex:1; position:relative;}
.bottom-tab-wrap a:after {content:" "; position:absolute; left:0; top:0; width:1px; height:100%; border-left:1px solid #ccc; color:#707070;}
/*动态样式*/
.post-container {width:100%;}
.post-wrapper {width:100%; background-color:#ffffff; margin:10px auto;}
.post-main {padding:10px 15px; color:#9a9a9a;}
.post-avatar {width:30px; height:30px;}
.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;}
.post-content {width:100%; font-size:14px; line-height:20px; height:100px; overflow:hidden; word-break:normal; word-wrap:break-word; text-align:justify;}
.post-all-content a {color:#136ec2;}
.post-interactive {width:100%; height:35px; line-height:35px; vertical-align:middle; border-top:1px solid #e6e6e6; background-color:#f8f9fb;}
.post-interactive-column,
.post-interactive-reply,
.post-interactive-praise {width:50%; text-align:center; float:left; font-size:13px;}
.more-wrap {width:100%;}
.more-events {width:100%; font-size:13px; text-align:center; margin:0 auto; padding: 5px 0; border-top:1px solid #e6e6e6; border-bottom:1px solid #e6e6e6; border-radius:3px; background-color:#f8f9fb; }
.border-bottom {border-bottom:1px solid #e6e6e6;}
.post-reply-wrap {width:100%;}
.post-reply-wrap:first-child {border-top:1px solid #ccc;}
.post-input-wrap {width:100%; position:fixed; bottom:0; background-color:#fff;}
.post-input-wrap2 {width:100%;}
.post-reply-row {margin:10px 15px; color:#9a9a9a; background-color:#fff; border-bottom:1px solid #f0f0f0;}
.post-reply-avatar {width:45px; height:30px; text-align:center; margin-right:10px;}
.post-reply-user {font-size:13px; text-align:left; margin-bottom:10px;}
.post-reply-content {font-size:13px; word-break:break-all; word-wrap:break-word; overflow:hidden; text-align:justify;}
.post-reply-content img {max-width:100%;}
.post-reply-content a {color:#136ec2;}
.post-reply-date, .post-reply-trigger {font-size:13px;}
.post-input-container {position:relative; padding-right:70px;}
.copy-input-container {position:relative; padding-right:70px;}
.copy-input {width:100%; height:18px; line-height:18px; padding:5px; vertical-align: middle; font-size:12px; border-radius:3px; position:absolute; left:-999em;}
.post-reply-input {width:100%; height:18px; max-height:54px; line-height:18px; vertical-align: middle; font-size:13px; border:1px solid #e6e6e6; outline:none; padding:5px; margin:0; border-radius:3px; overflow-y:auto; resize:none; background-color:#f0eff4;}
.post-reply-submit {position:absolute; font-size:13px; height:30px; line-height:30px; vertical-align:middle; padding:0 8px; color:#fff; background-color:#269ac9; outline:none; border:none; top:0; right:0;}
.reply-icon {background:url(/images/wechat/icon_list.gif) -150px -155px no-repeat; width:20px; height:20px; display:inline-block; vertical-align:middle;}
.praise-icon {background:url(/images/wechat/icon_list.gif) -36px -88px no-repeat; width:20px; height:20px; display:inline-block; vertical-align:middle;}
.praised-icon {background:url(/images/wechat/icon_list.gif) -152px -86px no-repeat; width:20px; height:20px; display:inline-block; vertical-align:middle;}
.num-block {display:inline-block; vertical-align:top;}
.post-op-banner {height:20px; line-height:20px; vertical-align:middle;}
/*20160628动态新样式*/
.post-dynamic-author {width:50%; height:30px; line-height:30px; font-size:14px; color:#5b5b5b; vertical-align:middle;}
.post-dynamic-time {height:30px; line-height:30px; vertical-align:middle;}
.post-dynamic-title {font-size:15px;}
.post-dynamic-from {width:50%; font-size:13px;}
.post-box-shadow {box-shadow: 0px 2px 8px rgba(146, 153, 169, 0.5);}
.post-reply-author {width:50%; height:20px; line-height:20px; font-size:12px; color:#5d5d5d; vertical-align:middle;}
.post-reply-time {height:20px; line-height:20px; vertical-align:middle;}
/* loading 弹框*/
.loading-bg {position:fixed; width:100%; height:100%; left:0; top:0; z-index:99; background:rgba(206, 206, 206, 0.3); overflow:hidden;}
.loading-box {position:absolute; top:50%; background:rgba(240,240,240, 0.5); width:160px; height:72px; left:50%; margin-top:-36px; margin-left:-80px; text-align:center;}
.loading-box img {margin-top: 3px; text-align: center;}
.loading-box span {display: block; font-size:12px;}
/*帖子锁定样式*/
.locked_btn_cir {background: url("/images/wechat/locked.png") 0 0 no-repeat; cursor: default;}
/*20150612加入班级样式*/
.add-class-box {position:fixed; width:80%; max-width:300px; min-width:240px; font-size:15px; color:#444; background-color:#fff; box-shadow: 0px 2px 8px rgba(146, 153, 169, 0.5); border-radius:5px; top:50%; left:50%; transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%); -moz-transform: translate(-50%,-50%); -webkit-transform: translate(-50%,-50%); -o-transform: translate(-50%,-50%);}
.add-class-tip {padding-top:1.2em; padding-bottom:.5em; font-weight:400;}
.class-number-input {width:80%; max-width:240px; height:28px; border:1px solid #ccc; padding-left:5px; margin:0 auto; display:block;}
.cancel-btn {width:49%; height:37px; line-height:37px; text-align:center; vertical-align:middle; border-top:1px solid #ccc;}
.submit-btn {width:49%; height:37px; line-height:37px; text-align:center; vertical-align:middle; border-top:1px solid #ccc;}
.slice {width:2%; text-align:center; border-top:1px solid #ccc;}
.slice-line {width:1px; height:37px; margin:auto; background:#ccc;}
/*20160613邀请码样式*/
.qr-code-wrap {width:100%; padding:40px 0; background-color:#3b94d6;}
.qr-code-box {width:225px; background-color:#fff; border-radius:3px; margin:0 auto;}
.share-class-name {font-size:18px; color:#3b3b3b; text-align:center; padding:12px; border-bottom:1px solid #cccccc;}
.qr-img-wrap {width:100%; border-bottom:1px dashed #ccc;}
.qr-code-img {margin:36px auto; display:block;}
.invitation-code-wrap {text-align:center; font-size:18px; color:#3b3b3b; padding:16px;}
.share-code-wrap {width:100%; background-color:#efeff4;}
.share-code-btn, .finish-btn {width:145px; height:35px; color:#fff; font-size:15px; line-height:35px; text-align:center; vertical-align:middle; background-color:#ff7239; margin:18px auto 20px auto; border-radius:50px; display:block;}
.share-code-instruction {max-width:228px; font-size:12px; color:#666; line-height:20px; margin:0 auto;}
/*20160613班级详情*/
.class-detail-name, .blue-title {width:100%; height:45px; line-height:45px; vertical-align:middle; background-color:#3b94d6; color:#fff; font-size:18px; text-align:center;}
.blue-title-sub {position:absolute; right:10px;}
.slice2 {width:2%; text-align:center; background-color:#fff; border-bottom:1px solid #ccc;}
.slice3 {width:1%; height:38px; text-align:center; background-color:#fff; border-bottom:1px solid #ccc;}
.slice-line2 {width:1px; height:38px; margin:auto; background:#ccc;}
.class-detail-tab {width:23%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-detail-tab2 {width:32%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-detail-tab3 {width:48%; height:38px; line-height:38px; font-size:13px; color:#444; background-color:#fff; float:left; text-align:center; vertical-align:middle; border-bottom:1px solid #ccc;}
.class-tab-active {border-bottom:3px solid #3b94d6;}
.tab-active-arrow {border-width:4px; position:absolute; top:41px; left:50%; transform:translate(-50%,0); border-color:#3b94d6 transparent transparent transparent; border-style:solid dashed dashed dashed;}
.class-search-wrap {padding:8px 12px; position:relative;}
.class-search-inner {padding:0 30px; background-color:#fff;}
.class-search-icon {position:absolute; top:16px; left:16px;}
.class-detail-search {width:100%; height:33px; color:#999; background-color:#fff; border:none; outline:none;}
.border-top {border-top:1px solid #ccc;}
.class-detail-row {width:100%; line-height:18px; padding:10px 0; border-bottom:1px solid #ccc; background-color:#fff;}
.class-member-row {width:100%; line-height:18px; padding:5px 0; border-bottom:1px solid #ccc; background-color:#fff; position:relative;}
.class-test-tip {text-align:center; font-size:13px; color:#444; padding-top:40px;}
.img-circle {border-radius:50% !important;}
.member-banner {height:24px; line-height:24px; text-align:center; vertical-align:middle; background-color:#dfdfdf;}
.resource-width {width:76%;}
.courseware-from-width {max-width:57%;}
.other-from-width {max-width:80%;}
.course-name-width {width:68%;}
/*20160614班级列表*/
.course-diff-row {width:100%; height:28px; line-height:28px; vertical-align:middle; background-color:#fff; border-bottom:1px solid #ccc;}
.course-list-row {width:100%; height:38px; line-height:38px; vertical-align:middle; border-top:1px solid #ccc; border-bottom:1px solid #ccc; background-color:#fff;}
.class-list {width:100%; border-bottom:1px solid #ccc;}
.class-list li {height:40px; line-height:40px; vertical-align:middle; margin:0 25px; border-left:1px solid #ccc; border-bottom:1px solid #ccc; position:relative;}
.class-list-name {max-width:75%; display:inline-block;}
.class-list-dot {position:absolute; top:13px; left:-8px;}
.border-bottom-none {border-bottom:none !important;}
.border-top-none {border-top:none !important;}
.students-amount {height:14px; line-height:14px; vertical-align:middle; padding:2px 5px; background-color:#e6e6e6; border-radius:10px;}
.new-class-btn {font-size:15px; color:#fff; background-color:#3b94d6; padding:10px 40px; border-radius:20px; display:inline-block; margin:0 auto;}
.join-class-btn {font-size:15px; color:#444; background-color:#ccc; padding:10px 40px; border-radius:20px; display:inline-block; margin:0 auto;}
.new-class-input {width:60%; color:#555; height:16px; line-height:16px; vertical-align:middle; border:none; outline:none; padding:8px 0;}
.class-list-setting {position:absolute; top:11px; right:10px;}
.class-setting-wrap {width:38px; height:38px; position:absolute; top:0; right:0;}
/*20160616登录注册*/
.login-wrap {padding:0 10px;}
.input-box-wrap {padding-right:17px;}
.input-box { -webkit-appearance: none; font-size: 15px;width:100%; height:18px; padding: 10px 0px 10px 5px; line-height:18px; border:1px solid #ccc; border-radius:5px;}
.login-op-wrap {height:30px; line-height:30px; vertical-align:middle;}
.login-box{display:inline-block; width:14px; height:14px; line-height:14px; text-align:center; vertical-align:middle; border:1px solid #ccc; background:#fff; border-radius:3px; color:#fff; cursor:pointer;}
.login-box.checked{background:#63c360; border:1px solid #63c360;}
.login-box.checked:after{content:url(/images/wechat/checked.png);}
.forget-psw-wrap {width:60px; margin:0 auto;}
.forget-psw {position:fixed; bottom:10px;}
/*二级回复*/
.mult-reply-container{ border:solid 1px #f3ddb3; background:#fffef4; padding:4px;color:#999;}
.mult-reply-content{ color:#555; font-size:13px;}
.mult-reply-hide{ text-align:center; display:block; font-size:14px; color:#aaa; border-bottom:1px solid #F3DDB3; padding:8px 0;}
.mult-reply-arrow{ color:#aaa; margin-right:10px; font-size:14px; font-weight:bold;}
/*20160729项目说明*/
.project-intro {line-height:2; width:120px; margin-left:auto; margin-right:auto;}
.project-intro li {position:relative;}
.project-intro-dot {font-size:25px; font-weight:bold; position:absolute; left:-10px; top:-13px;}
/*新建说明*/
.new-tip {line-height:2;}
.new-tip li {position:relative; padding-left:10px;}