增加答题功能

smart_class
educoder_weapp 5 years ago
parent c795112f0a
commit 7bbbe466c9

1
.gitignore vendored

@ -13,6 +13,7 @@ $RECYCLE.BIN/
lib_refer
towxml
project.config.json
.idea
# Node.js
node_modules/

@ -1,21 +1,22 @@
# 功能介绍
- 学员可以在点击右下角”加入课堂”选择课程加入,教员可以在“加入课堂中”新建课程
## 教室
- 学员可以输入邀请码进入课堂
- 长按相应课程可以退出学习
- 进入教室界面会显示在位,头像为彩色,若退出课堂界面则会显示灰色头像
- 进入课堂界面会显示在位,头像为彩色,若退出课堂界面则会显示灰色头像
- 教员在课堂界面中可以直观地看到学员在位情况,可以选择学员让其起立回答问题,并且对学员可以进行加分、减分操作
- 教员在教室界面中可以直观地看到学员在位情况,可以选择学员让其起立回答问题,并且对学员可以进行加分、减分操作
- 学员可以收到教员让其起立提问、回答的提示,还可以点击“我要提问、回答”
- 课堂内有讨论区,可以交流
- 教室内有讨论区,可以交流
## 课程资源
- 在课堂界面右下角进入“资源”可以查看本课堂的课程文件资源 # 发布版要长按白色底部栏进入
- 在课程界面进入“资源”可以查看本课堂的课程文件资源
- 教员可以在课程的设置界面中更新课程的名称,还可以将学员移除本课程的学习
- 支持打开ppt doc xls pdf文件
## 其他
## 试卷作答
- 用户可以在设置中更改姓名、用户名
- 学员在课程内可以看到老师发布的试卷,并且回答

@ -38,35 +38,17 @@ App({
console.log("onLauch");
console.log(this.client.get_user_info({
success: res=>{
console.log("userinfo get success");
console.log("app.js: userinfo get success");
console.log(res);
console.log(this);
if(res.data.user_id == 2){
this.enter_login();
}
},
fail:error=>{
console.log("get user info fail");
console.warn("app.js: get user info fail");
this.enter_login();
}
}));
login();
//.then((user) => {
// //console.log(user);
// //console.log(AV.User.current());
// if (!user.get("name_setted")) {
// wx.navigateTo({
// url: '../user/user',
// });
// wx.showToast({
// title: '请修改你的姓名',
// duration: 5000,
// icon: "none"
// })
// }
// });
// wx.cloud.init({
// env: 'test-tkkvk'
// })
}
});

@ -1,6 +1,9 @@
{
"pages": [
"pages/my_courses/my_courses",
"pages/courses/courses",
"pages/exercise/exercise",
"pages/setting/setting",
"pages/changeuser/changeuser",
"pages/user/user",
@ -12,8 +15,11 @@
"pages/createclass/createclass",
"pages/login/login",
"pages/test/test",
"pages/courses/courses",
"pages/course_detail/course_detail"
"pages/course_detail/course_detail",
"pages/files/files",
"pages/exercises/exercises",
"pages/mark_detail/mark_detail"
],
"window": {
"backgroundTextStyle": "dark",

@ -30,33 +30,3 @@ page {
.warning{
color: orange;
}
.lab {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}
.lab .status image {
width: 70px;
height: 70px;
border-radius: 100%;
}
.lab .hint {
text-align: center;
width: 80%;
}
.lab .interactive {
width: 80%;
}
.lab .interactive input {
border-bottom: 4rpx solid #EEE;
}
.lab .command {
height: 200rpx;
}
.lab .command button {
margin: 10px;
}

@ -1,9 +1,9 @@
import {Account, Course} from "./eduapi"
import {Account, Course, Exercise, ExerciseQuestion} from "./eduapi"
import {Session} from "./requests";
import {Cookie} from "./cookie";
/**
* 客户端类其method实现客户端各种操作将接口Promise化从而使其调用更加方便简洁
* 客户端类其method实现客户端各种操作将接口Promise化
* 要在此处实现网络数据及cookie的缓存
*/
@ -16,7 +16,23 @@ export class Client{
}
this.load_cached_cookies();
this.current_user = {};
console.log(this.session);
this.load_current_user();
}
load_current_user(){
var value = wx.getStorageSync('current_user');
if(value) {
this.current_user = value;
console.log("read current_user from storage");
console.log(this.current_user);
}
}
save_current_user(){
console.log("save current user to storage");
console.log(this.current_user);
wx.setStorageSync("current_user", this.current_user);
}
clear_current_user(){
wx.setStorageSync("current_user", {});
}
load_cached_cookies(){
try {
@ -28,17 +44,17 @@ export class Client{
if (value) {
this.session.set_cookie(new Cookie(value));
}
console.log("read cookies");
console.log("read cookies from wx.Storage:");
console.log(this.session.cookies);
} catch (e) {
// Do something when catch error
console.log("there is not cachede cookie")
console.error("there is not cached cookie")
console.error(e);
}
}
save_cookies(){
for(var cookie of Object.values(this.session.cookies)){
console.log("client save cookie");
console.log("client save new cookie");
console.log(cookie);
cookie.save();
}
@ -68,6 +84,8 @@ export class Client{
success: res => {
this.save_cookies();
this.current_user = {...this.current_user, ...res.data};
console.log("current_user info update");
console.log(this.current_user);
this.get_user_info();
if (typeof success == "function") {
success(res);
@ -94,15 +112,38 @@ export class Client{
}, complete: complete});
})
}
register({login, password, code, success, fail, complete}){
return new Promise((resolve, reject) => {
Account.register({session: this.session, login:login, password:password, code:code,
complete:complete,
success: res=>{
this.save_cookies();
if(typeof success == "function"){
success(res);
}
resolve(res);
},
fail:error=>{
if(typeof fail == "function") {
fail(error);
}
reject(error)
}
});
});
}
get_user_info({success, fail, complete}={}){
return new Promise((resolve, reject) => {
Account.get_user_info({session: this.session, complete: complete,
success: res=>{
this.current_user = {...this.current_user, ...res.data};
console.log("current_user info update");
console.log(this.current_user);
if(typeof success == "function"){
success(res);
}
resolve(res);
this.save_current_user();
},
fail: error=>{
if(typeof fail == "function"){
@ -113,35 +154,60 @@ export class Client{
})
});
}
register({login, password, code, success, fail, complete}){
get_verification_code_for_register({login, success, fail, complete}){
return Account.get_verification_code({session: this.session, login: login, type: 1,
fail: fail, complete: complete, success: success});
}
get_verification_code_for_reset_password({}){}
search_courses({limit=20, page=1, order="all", search="", success, fail, complete}={}){
return new Promise((resolve, reject) => {
Account.register({session: this.session, login:login, password:password, code:code,
complete:complete,
Course.search({session: this.session, page: page, order: order, search: search, complete: complete,
success: res=>{
this.save_cookies();
if(typeof success == "function"){
success(res);
}
resolve(res);
},
fail:error=>{
if(typeof fail == "function") {
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error)
reject(error);
}
});
});
}
get_verification_code_for_register({login, success, fail, complete}){
return Account.get_verification_code({session: this.session, login: login, type: 1,
fail: fail, complete: complete, success: success});
get_course_info({course_id, success, fail, complete}){
return new Promise((resolve, reject) => {
Course.get_course_info({
session: this.session,
course_id: course_id,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
}
get_verification_code_for_reset_password({}){}
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
})
});
search_courses({limit=20, page=1, order="all", search="", success, fail, complete}={}){
}
get_user_courses({page=1, per_page=16, success, fail, complete}={}){
return new Promise((resolve, reject) => {
Course.search({session: this.session, page: page, order: order, search: search, complete: complete,
Account.get_user_courses({
session: this.session,
page: page,
per_page: per_page,
user: this.current_user.login,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
@ -157,7 +223,6 @@ export class Client{
});
});
}
join_course({invite_code, professor=null,assistant_professor=null,student=null, success, fail, complete}){
return new Promise((resolve, reject)=>{
Course.join({session: this.session, invite_code: invite_code, professor: professor, assistant_professor: assistant_professor, student: student, complete: complete,
@ -176,7 +241,161 @@ export class Client{
})
});
}
search_exercise(){}
start_answer_exercise(){}
answer_exercise_question(){}
get_course_files({course_id, page_size=15, page=1,search="",sort=0, sort_type="created_on", success, fail, complete}){
return new Promise((resolve, reject) => {
Course.get_files({
session: this.session,course_id:course_id, page_size: page_size, page:page, search: search, sort: sort, sort_type: sort_type, complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof success == "function"){
fail(error);
}
reject(error);
}
});
});
}
get_course_students({course_id, order=1,sort="asc",page=1, limit=20, course_group_id="", success, fail, complete}){
return new Promise((resolve, reject) => {
Course.get_students({
session: this.session,
course_id: course_id,
order: order,
sort: sort,
page: page,
limit: limit,
course_group_id: course_group_id,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof success == "function"){
fail(error);
}
reject(error);
}
})
})
}
search_exercises({course_id, type="", page=1, limit=15, success, fail, complete}){
return new Promise((resolve, reject) => {
Exercise.search({
session: this.session,
course_id: course_id,
type: type,
page: page,
limit: limit,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
})
});
}
start_answer_exercise({exercise_id, success, fail, complete}){
return new Promise((resolve, reject) => {
Exercise.start_answer({
session: this.session,
exercise_id: exercise_id,
login: this.current_user.login,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
})
});
}
answer_exercise_question({question_id, exercise_choice_id,answer_text ,success, fail, complete}){
return new Promise((resolve, reject) =>{
ExerciseQuestion.answer({
session: this.session,
question_id: question_id,
answer_text: answer_text,
exercise_choice_id: exercise_choice_id,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
})
} );
}
save_exercise({exercise_id, success, fail, complete}){
return new Promise((resolve, reject) => {
Exercise.save({
session: this.session,
exercise_id: exercise_id,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof success == "function"){
fail(error);
}
reject(error);
}
})
});
}
commit_exercise({exercise_id, commit_method=1, success, fail , complete}){
return new Promise((resolve, reject) => {
Exercise.commit({
session: this.session,
exercise_id: exercise_id,
commit_method: commit_method,
complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
};
resolve(res);
},
fail: error=>{
if(typeof success == "function"){
fail(error);
}
reject(error);
}
})
});
}
}

@ -13,11 +13,9 @@ export class Cookie{
}
analyse_cookie(str){
this.string = str.slice(0, str.indexOf(";"));
//console.log(this.string);
let idx = this.string.indexOf("=");
this.key = this.string.slice(0, idx);
this.value = this.string.slice(idx+1);
//console.log(this);
}
toString(){
return this.string;
@ -26,7 +24,7 @@ export class Cookie{
save(){
if(!this.key){
throw new Error("没有键值");
console.error("cookie保存时: 没有键值key");
}
wx.setStorageSync(this.key, this.origin_str);
}

@ -90,6 +90,17 @@ export class Account{
complete: complete
})
}
static get_user_courses({session,user,page=1, per_page=16, success, fail, complete}){
let data = {page: page, per_page: per_page};
return session.request({
url: api_base_url + "/users/"+user +"/courses.json",
method: "GET",
data: data,
success: success,
fail: fail,
complete: complete
})
}
}
export class Course{
@ -142,6 +153,17 @@ export class Course{
complete: complete
})
}
static get_files({session, course_id, page_size=15, page=1,search="",sort=0, sort_type="created_on", success, fail, complete}){
let data = {course_id: course_id, page_size: page_size, page: page, search: search, sort: sort, sort_type: sort_type};
return session.request({
url: api_base_url + "/files.json",
method: "GET",
data: data,
success: success,
fail: fail,
complete: complete
})
}
static get_students({session, course_id, order=1,sort="asc",page=1, limit=20, course_group_id="", success, fail, complete}){
let data = {
order: order,
@ -165,13 +187,22 @@ export class Course{
complete: complete
})
}
static get_course_info({session, course_id, success, fail, complete}){
session.request({
url: api_base_url + "/courses/"+course_id+"/top_banner.json",
method : "GET",
success: success,
fail: fail,
complete: complete
})
}
}
export class Exercise{
static search({session,course_id,page=1, limit=15, success, fail, complete}){
let data = {page:page, limit:limit};
return session.request({
url: api_base_url + "/courses/"+course_id+"/exercises,json",
url: api_base_url + "/courses/"+course_id+"/exercises.json",
method: "GET",
data: data,
success: success,
@ -185,6 +216,41 @@ export class Exercise{
url: api_base_url + "/exercises/" + exercise_id + "/start_answer.json",
method: "GET",
data: data,
success: res=>{
if("status" in res.data){
if(res.data.status<0){
fail(new Error(res.data.message));
return;
}
/*switch (res.data.status) {
case -1:
fail(new Error("???"));
return;
}*/
}
if(typeof success == "function") {
success(res);
}
},
fail: fail,
complete: complete
})
}
static save({session, exercise_id, success, fail, complete}){
return session.request({
url: api_base_url + "/exercises/"+exercise_id+"/begin_commit.json",
method: "GET",
success: success,
fail: fail,
complete: complete
})
}
static commit({session, exercise_id, commit_method=1, success, fail, complete}){
let data = {commit_method: commit_method};
return session.request({
url: api_base_url+ "/exercises/"+exercise_id+"/commit_exercise.json",
method: "POST",
data: data,
success: success,
fail: fail,
complete: complete
@ -193,14 +259,46 @@ export class Exercise{
}
export class ExerciseQuestion {
static answer({session, question_id, exercise_choice_id, login, success, fail, complete}){
let data = {exercise_choice_id: exercise_choice_id};
static answer({session, question_id, exercise_choice_id, answer_text, success, fail, complete}){
let data = {};
if(exercise_choice_id){data["exercise_choice_id"] = exercise_choice_id;}
if(answer_text){data["answer_text"] = answer_text}
return session.request({
url: api_base_url + "/exercise_questions/" + question_id +"/exercise_answer.json",
url: api_base_url + "/exercise_questions/" + question_id +"/exercise_answers.json",
method: "POST",
data: data,
success: success,
fail: fail,
success: res=>{
if("status" in res.data){
if(res.data.status<0){
fail(new Error(res.data.message));
return;
}
/*switch (res.data.status) {
case -1:
fail(new Error("???"));
return;
}*/
}
if(typeof success == "function") {
success(res);
}
},
fail: error=>{
// console.error("wx.request error:");
// console.log(error);
// console.log(error.toString());
// console.log(error.message);
// console.log(error.errMsg);
let e = error;
if(!("message" in error)){
if("errMsg" in error){
e = new Error(error.errMsg);
}
}
if(typeof fail == "function") {
fail(e);
}
},
complete: complete
})
}

@ -0,0 +1,10 @@
/**
* @todo: Error类, to be finished
*/
export default class EduError extends Error{
constructor({message=null, code=-1}){
super(message);
this.code = code;
}
}

@ -13,10 +13,12 @@ export class Session {
}
get cookie_str(){
let cookie_strs = Object.values(this.cookies).map(cookie=>cookie.toString());
//console.log("cookie_strs:"+cookie_strs);
return cookie_strs.join(";");
}
request({url, data, header, method, dataType, responseType, success, fail, complete}) {
console.log("request data and headers: ");
console.log({url: url, data: data, header: {...header, "Cookie": this.cookie_str}, method: method, dataType: dataType, responseType: responseType})
return wx.request({
url: url,
data: data,
@ -27,25 +29,24 @@ export class Session {
success: (res) => {
if ("cookies" in res) {
let cookies = res["cookies"];
//console.log(cookies);
console.log("request: this:");
console.log(this);
for (var i = 0; i < cookies.length; i++) {
this.set_cookie(new Cookie(cookies[i]));
}
console.log("set new cookies:");
console.log(this.cookies);
} else {
console.log("request.js: no cookies in this request");
console.warn("request.js: no cookies setted in this request");
}
//console.log(this.cookies);
if (typeof success == "function") {
success(res);
} else {
console.warn("requests.session.request success is not function");
console.warn("requests.session.request.success is not function");
}
},
fail: fail,
complete: complete
});
}
uploadFile({url, filePath, name, header, formData, success, fail, complete}){
return wx.uploadFile({
@ -69,4 +70,4 @@ export class Session {
complete: complete
})
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

@ -3,7 +3,7 @@ const AV = require('../lib/av-live-query-weapp-min');
//数据储存模板--分数
class Grade extends AV.Object {
get mark() {
return this.get('done');
return this.get('mark');
}
set mark(value) {
this.set('mark', value);
@ -33,7 +33,25 @@ class Grade extends AV.Object {
this.set("date", value)
}
add_mark(value){
this.increment(value);
this.increment("mark",value);
}
get edu_course_id(){
return this.get("edu_course_id");
}
set edu_course_id(value){
this.set("edu_course_id", value);
}
get presence(){
return this.get("presence");
}
set presence(value){
this.set("presence", value)
}
get edu_account_login(){
return this.get("edu_account_login");
}
set edu_account_login(value){
this.set("edu_account_login", value);
}
}

@ -19,6 +19,24 @@ class Message extends AV.Object{
set class(value){
this.set("class", value);
}
get sender_name(){
return this.get("sender_name");
}
set sender_name(value){
this.set("sender_name", vlaue);
}
get edu_account_login() {
return this.get("edu_account_login");
}
set edu_account_login(value) {
this.set("edu_account_login", value);
}
get edu_course_id() {
return this.get("edu_course_id");
}
set edu_course_id(value) {
this.set("edu_course_id", value);
}
}
AV.Object.register(Message, "Message");

@ -7,6 +7,7 @@ class Presence extends AV.Object{
get user(){
return this.get("user");
}
set class(value){
this.set("class", value);
}
@ -26,7 +27,7 @@ class Presence extends AV.Object{
this.set("present", value);
}
get mark() {
return this.get('done');
return this.get('mark');
}
set mark(value) {
this.set('mark', value);
@ -34,6 +35,12 @@ class Presence extends AV.Object{
add_mark(value) {
this.increment(value);
}
get edu_account_login() {
return this.get("edu_account_login");
}
set edu_account_login(value) {
this.set("edu_account_login", value);
}
enter(){
console.log("presence.enter");
console.log(this);

@ -6,7 +6,7 @@ Page({
/**
* 页面的初始数据
*/
md: '# 功能介绍\n\n- 学员可以在点击右下角”加入课堂”选择课程加入,教员可以在“加入课堂中”新建课程\n\n- 长按相应课程可以退出学习\n\n- 进入课堂界面会显示在位,头像为彩色,若退出课堂界面则会显示灰色头像\n\n- 教员在课堂界面中可以直观地看到学员在位情况,可以选择学员让其起立回答问题,并且对学员可以进行加分、减分操作\n\n- 学员可以收到教员让其起立提问、回答的提示,还可以点击“我要提问、回答”\n\n- 课堂内有讨论区,可以交流\n\n- 在课堂界面右下角进入“资源”可以查看本课堂的课程文件资源\n - 发布版要长按白色底部栏进入\n\n- 教员可以在课程的设置界面中更新课程的名称,还可以将学员移除本课程的学习\n\n## 其他\n \n- 用户可以在设置中更改姓名、用户名\n\n\n.',
md: '# 功能介绍\n\n## 教室\n- 学员可以输入邀请码进入课堂\n\n- 进入教室界面会显示在位,头像为彩色,若退出课堂界面则会显示灰色头像\n\n- 教员在教室界面中可以直观地看到学员在位情况,可以选择学员让其起立回答问题,并且对学员可以进行加分、减分操作\n\n- 学员可以收到教员让其起立提问、回答的提示,还可以点击“我要提问、回答”\n\n- 教室内有讨论区,可以交流\n\n## 课程资源\n\n- 在课程界面进入“资源”可以查看本课堂的课程文件资源\n\n- 支持打开ppt doc xls pdf文件\n\n## 试卷作答\n\n- 学员在课程内可以看到老师发布的试卷,并且回答',
data: {
article: {}

@ -1,4 +1,4 @@
<import src="/towxml/entry.wxml"/>
<view class="container">
<template is="entry" data="{{...article}}" class="about"/>
<template is="entry" data="{{...article}}"/>
</view>

@ -12,6 +12,6 @@
/**主题配色(深色样式)**/
@import '/towxml/style/theme/dark.wxss';
.about{
padding-bottom: 4px;
.container{
padding-bottom: 40rpx;
}

@ -1,47 +1,34 @@
// pages/classroom/classroom.js
const AV = require("../../lib/av-live-query-weapp-min")
const AV = require("../../lib/av-live-query-weapp-min");
const { jsonify } = require('../../utils/leancloudutils');
const bind = require("../../lib/live-query-binding")
const Message = require("../../model/message")
const bind = require("../../lib/live-query-binding");
const Message = require("../../model/message");
const Grade = require("../../model/grade");
const Presence = require("../../model/presence");
const app = getApp();
Page({
/**
页面的初始数据
students: 该课程所有的学生
元素student
student.objectId 该学生的主键唯一
student.username 学生的用户名是唯一就像微信号一样
student.name 学生的姓名
student.present 是否出席
student.isasking :0:没有提问,1:提问,2:请回答
*/
class:null,
students: [],
presences: [],
my_presence: null,
asking_presence: null,
idStudentMap: {},
data: {
course: null,
loading: true,
students: [], // 该课程所有的学生, 元素类型见上文中的student
student_num: 0,
current_user: null, //目前登陆的用户,类型为对象属性有objectIdusername, name
teacher: null,
select_stu_id: '',
//该课程教员,类型为对象
//请在进入界面时判断用户是否为教员以给与权限或更改界面
//属性如下objectId, username, name
class_name: "", //课程名称
class_id: "", //该课程的主键(编号)
students: [],
select_stu_login:"",
message_text: "",
messages: [],
show_conversation: true
},
enter_mark_detail({currentTarget:{dataset}}){
wx.navigateTo({
url: '../mark_detail/mark_detail?course_id='+this.course_id,
})
},
pull_messages: function(){
query = new AV.Query("Message");
query.equalTo("class", this.class);
query.include("sender");
set_messages = this.set_messages.bind(this);
let query = new AV.Query("Message");
query.equalTo("edu_course_id", this.course_id);
const set_messages = this.set_messages.bind(this);
return AV.Promise.all([query.find().then(set_messages), query.subscribe()]).then(([messages, subscription]) => {
this.messageSubscription = subscription;
if (this.messageUnbind) this.messageUnbind();
@ -51,15 +38,11 @@ Page({
set_messages: function(messages){
console.log("set_messages");
messages = messages.map(message=>{
sender = message.get("sender");
console.log(this.idStudentMap);
console.log(sender.id);
console.log(!sender.get("name") && sender.id in this.idStudentMap)
if(!sender.get("name")&&sender.id in this.idStudentMap){
sender = this.idStudentMap[sender.id];
let sender_login = message.edu_account_login;
let senders_ = this.students.filter(student=>student.login==sender_login)
if(senders_.length==1){
message.set("sender_name", senders_[0]["name"]);
}
message.set("sender_name", sender.get("name"));
message.set("sender_username", sender.get("username"));
return message;
})
console.log(jsonify({ messages }));
@ -69,11 +52,12 @@ Page({
send_message:function(event){
let {message_text} = this.data;
if(message_text.trim()==""){return;}
message = new Message({
let message = new Message({
text: message_text,
class: this.class,
sender: AV.User.current()
})
edu_account_login: this.current_user.login,
edu_course_id: this.course_id,
sender_name: this.current_user.real_name||"未命名",
});
message.save().then(()=>{
this.setData({message_text: ""});
console.log("send_message")
@ -89,36 +73,23 @@ Page({
update_message:function({detail:{value}}){
this.setData({message_text: value});
},
enter_setting: function(event){
wx.navigateTo({
url: '../classsetting/classsetting?class_id='+this.data.class_id+"&teacher_id="+this.data.teacher.objectId+"&classname="+this.data.class_name,
})
},
enter_detail: function(event){
wx.navigateTo({
url: '../classdetail/classdetail?class_id='+this.data.class_id,
})
},
select_stu: function(event){
id = event.currentTarget.dataset.id;
if(id=='none'){
id="";
}
this.setData({select_stu_id: id});
let login = event.currentTarget.dataset.login;
console.log(event);
this.setData({select_stu_login: login});
console.log(this.data.select_stu_login);
},
set_isasking: function(event){
userid = event.currentTarget.dataset.id;
status = event.currentTarget.dataset.status;
let login = event.currentTarget.dataset.login;
let status = event.currentTarget.dataset.status;
console.log("set_isasking");
this.asking_presence = this.presences.filter(presence=>presence.get("user").id==userid)[0];
console.log(this.asking_presence);
this.asking_presence.isasking = status;
let asking_presence = this.presences.filter(presence=>presence.get("edu_account_login")==login)[0];
console.log(asking_presence);
asking_presence.isasking = status;
wx.showLoading({
title: '请稍候',
})
this.asking_presence.save().then(()=>{
});
asking_presence.save().then(()=>{
wx.hideLoading();
}, ()=>{
wx.hideLoading();
@ -130,106 +101,135 @@ Page({
},
add_mark: function(event){
console.log("add_mark");
id = event.currentTarget.dataset.id;
mark = event.currentTarget.dataset.mark;
let login = event.currentTarget.dataset.login;
let mark = event.currentTarget.dataset.mark;
console.log(this.presences);
presence = this.presences.filter(presence => presence.get("user").id == id)[0];
let presence = this.presences.filter(presence => presence.get("edu_account_login") == login)[0];
if(presence==null){
console.warn("没有选择学生");
console.warn("没有学生Presence");
presence = new Presence({
edu_account_login: login,
edu_course_id: this.course_id,
present: false,
mark: 0
})
}
presence.increment("mark", mark).save().then(()=>{
presence.increment("mark", mark);
var grade = new Grade();
console.log(grade);
grade.edu_account_login = login;
grade.edu_course_id = this.course_id;
grade.mark = mark;
presence.save().then(()=>{grade.save()}).then(()=>{
wx.showToast({
title: '操作成功',
icon:"none"
})
}).catch(error=>console.error(error.message));
}
).catch(console.error);
},
pull_presence: function(){
var query = new AV.Query("Presence");
query.equalTo("class", this.class);
query.include("user");
set_presence = this.set_presence.bind(this);
let query = new AV.Query("Presence");
query.equalTo("edu_course_id", this.course_id);
const set_presence = this.set_presence.bind(this);
return AV.Promise.all([query.find().then(set_presence), query.subscribe()]).then(([presences, subscription])=>{
this.presenceSubscription = subscription;
if(this.presenceUnbind) this.presenceUnbind();
console.log("shwo set_presence");
console.log("show set_presence");
console.log(presences);
console.log(set_presence);
this.presenceUnbind = bind(subscription, presences, set_presence);
}).catch(error=> console.error(error.message));
})
},
set_presence: function(presences){
this.presences = presences;
console.log("set_presence");
console.log(presences);
pull_presence = this.pull_presence.bind(this);
this.presences = presences;
students = this.presences.map((presence)=>{
student = presence.get("user");
if(student.get("username")==null){
students = this.students.filter(stu=>stu.id==student.id)
if(students.length==1){
student = students[0];
}else{
console.warn("pull_presence because new student join");
pull_presence();
return;
//console.log("Set_presence");
//console.log(this);
let students = this.students.concat().map(student=>{
student["mark"]=0;
student["isasking"]=0;
student["present"]=false;
return student;
});//拷贝
for(var presence of presences){
let student_login = presence.get("edu_account_login");
if(presence.edu_account_login==this.current_user.login){
this.my_presence = presence;
}
for(var i=0;i<students.length;i++){
if(students[i].login==student_login){
students[i]["present"] = presence.present;
students[i]["isasking"] = presence.isasking;
students[i]["mark"] = presence.mark;
break;
}
this.idStudentMap[student.id]=student;
student.set("present", presence.get("present"));
student.set("isasking",presence.get("isasking"));
student.set("mark", presence.get("mark"));
if(student.id==AV.User.current().id){
this.my_presence = presence;
this.setData({current_user:student.toJSON()});
}
return student;
});
this.students = students;
this.setData(jsonify({students}));
this.setData({loading:false})
}
console.log(students);
this.setData({students: students});
return presences;
},
pull_class: function(class_id){
query = new AV.Query("Class_");
query.equalTo("objectId", class_id);
query.include("teacher");
return query.find().then((classes) => {
this.class = classes[0];
teacher = this.class.get("teacher");
teacher = teacher.toJSON();
this.setData({
class_name: this.class.get("name"),
class_id: this.class.get("objectId"),
teacher: teacher
});
}).catch(error=>console.error(error.message))
/**new api below: */
pull_course: function(){
return app.client.get_course_info({course_id: this.course_id})
.then(res=>{
this.setData({course: res.data});
wx.setNavigationBarTitle({
title: this.data.course.name
})
}).catch(console.error);
},
pull_students: function(){
return app.client.get_course_students({course_id: this.course_id})
.then(res=>{
this.students = res.data.students;
}).catch(console.error);
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.course_id = options.id;
this.current_user = app.client.current_user;
wx.showLoading({
title: '加载中'
})
this.setData({current_user: AV.User.current().toJSON()});
this.class_id = options.class_id;
this.class = AV.Object.createWithoutData("Class_", this.class_id);
this.pull_presence.bind(this)().then((presences) => {
this.my_presence.enter();
title: '加载中',
});
this.pull_class.bind(this)(this.class_id)
this.pull_course();
this.pull_students()
.then(()=>{
this.pull_presence()
.then(() => {
wx.setNavigationBarTitle({
title: this.data.class_name,
if (this.my_presence == null) {
this.my_presence = new Presence({
edu_account_login: this.current_user.login,
edu_course_id: this.course_id,
present: true
});
this.my_presence.save();
}else{
this.my_presence.enter();
}
})
.then(() => {
wx.hideLoading();
this.setData({ loading: false });
})
.catch(error => {
console.error(error);
wx.hideLoading();
wx.showToast({
title: '加载失败,请刷新重试',
icon: "none"
})
wx.hideLoading();//better place??
});
this.pull_messages.bind(this)();
console.log("onLoad");
});
this.pull_messages();
},
/**
@ -274,15 +274,31 @@ Page({
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
console.log(this.idStudentMap);
this.pull_presence.bind(this)();
this.pull_class.bind(this)(this.class_id)
.then(() => {
wx.setNavigationBarTitle({
title: this.data.class_name,
})
this.pull_course();
this.pull_students()
.then(()=>{
this.pull_presence().then(() => {
if (this.my_presence == null) {
this.my_presence = new Presence({
edu_account_login: this.current_user.login,
edu_course_id: this.course_id,
present: true
});
this.my_presence.save();
} else {
this.my_presence.enter();
}
);
}).then(()=>{
this.setData({loading: false});
}).catch(error => {
console.error(error);
wx.showToast({
title: '加载失败,请刷新重试',
icon: "none"
})
});
});
this.pull_messages();
},
/**
@ -298,4 +314,4 @@ Page({
onShareAppMessage: function () {
console.log("onShareAppMessage");
}
})
});

@ -1,5 +1,5 @@
<movable-area>
<view class="classroom" bindtap="select_stu" data-id="none">
<movable-area bindtap="select_stu" data-login="">
<view class="classroom">
<movable-view wx:if="{{show_conversation&&!loading}}" direction="all" y="{{240}}">
<myicon type="close" class="close" bindtap="close_conversation"></myicon>
<scroll-view scroll-y="{{true}}" class="message-list">
@ -20,14 +20,14 @@
</view>
</movable-view>
<text wx:if="{{!loading}}" class="hint" >课程名称:{{class_name}} 教员姓名:{{teacher.name}}</text>
<view wx:if="{{(students.length==0 || students.length==1 && students[0].objectId==current_user.objectId)&& !loading}}" class="no-student-view">
<text wx:if="{{!loading}}" class="hint" >课程名称:{{course.name}} 教员姓名:{{course.teacher_name}}</text>
<view wx:if="{{students.length==0 && !loading}}" class="no-student-view">
<image src="../../images/cry.png" class="no-student"></image>
<text class="no-student">还没有学员加入</text>
</view>
<view class="student-list">
<view class="student-list" wx:if="{{!loading}}">
<block wx:for="{{students}}" wx:for-item="student" wx:key="objectId">
<view class="{{teacher.objectId==current_user.objectId?'student selectable':'student'}}" hidden="{{teacher.objectId==student.objectId}}" catchtap="select_stu" data-id="{{student.objectId}}">
<view class="{{course.course_identity==2?'student selectable':'student'}}" catchtap="select_stu" data-login="{{student.login}}">
<myicon wx:if="{{!student.present}}" class="student-icon" type="absent_student" size="36"></myicon>
<myicon wx:elif="{{student.isasking==1}}" class="student-icon" type="question" size="36" color="red"></myicon>
<myicon wx:elif="{{student.isasking==0}}" class="student-icon" type="present_student" color="#00ff00" size="36"></myicon>
@ -38,13 +38,13 @@
</block>
</view>
<view class="operation-list">
<view wx:if="{{!loading}}" class="teacher-operation" hidden="{{teacher.objectId!=current_user.objectId || select_stu_id==''}}">
<button type="primary" catchtap="add_mark" data-id="{{select_stu_id}}" data-mark="{{-1}}">减一分</button>
<button type="primary" catchtap="add_mark" data-id="{{select_stu_id}}" data-mark="{{1}}">加一分</button>
<button type="primary" catchtap="add_mark" data-id="{{select_stu_id}}" data-mark="{{2}}">加两分</button>
<button type="primary" catchtap="set_isasking" data-id="{{select_stu_id}}" data-status="{{2}}">请起立</button>
<view wx:if="{{!loading}}" class="teacher-operation" hidden="{{course.course_identity!=2 || select_stu_login==''}}">
<button type="primary" catchtap="add_mark" data-login="{{select_stu_login}}" data-mark="{{-1}}">减一分</button>
<button type="primary" catchtap="add_mark" data-login="{{select_stu_login}}" data-mark="{{1}}">加一分</button>
<button type="primary" catchtap="add_mark" data-login="{{select_stu_login}}" data-mark="{{2}}">加两分</button>
<button type="primary" catchtap="set_isasking" data-login="{{select_stu_login}}" data-status="{{2}}">请起立</button>
</view>
<view wx:if="{{!loading}}" class="student-operation" hidden="{{teacher.objectId==current_user.objectId}}">
<view wx:if="{{!loading}}" class="student-operation" hidden="{{course.course_identity!=5}}">
<button hidden="{{current_user.isasking!=0}}" type="primary" catchtap="set_isasking" data-id="{{current_user.objectId}}" data-status="{{1}}">我要提问/回答</button>
<button hidden="{{current_user.isasking!=1}}" type="primary" catchtap="set_isasking" data-id="{{current_user.objectId}}" data-status="{{0}}">取消提问</button>
<text hidden="{{current_user.isasking!=2}}" class="warning">请起立提问/回答</text>
@ -52,9 +52,9 @@
</view>
</view>
<view wx:if="{{!loading}}" class="footer white">
<text class="tappable class-setting" hidden="{{teacher.objectId!=current_user.objectId}}" bindtap="enter_setting" data-id="{{class_id}}">设置</text>
<!--text class="tappable class-setting" hidden="{{course.course_identity!=2}}" bindtap="enter_setting" data-id="{{class_id}}">设置</text-->
<text hidden="{{teacher.objectId==current_user.objectId}}">我的得分:{{current_user.mark}}分</text>
<text class="tappable class-detail" bindtap="enter_detail">资源</text>
<text class="tappable mark-detail" bindtap="enter_mark_detail">加分记录</text>
</view>
</view>
</movable-area>

@ -1,6 +1,7 @@
movable-area{
height: 100%;
width: 100%;
margin-bottom: 44px;
}
movable-view{
@ -71,7 +72,7 @@ movable-view{
position: absolute;
}
.class-detail{
.mark-detail{
right: 0;
}
@ -103,7 +104,8 @@ button{
vertical-align: center;
align-items: center;
align-self: center;
display: flex;
flex-direction: column;
}
text.no-student{
font-size: 16px;

@ -5,14 +5,20 @@ Page({
* 页面的初始数据
*/
data: {
course: {}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({"course.id": options.id})
if(options.course_name && options.course_name!="undefined"){
wx.setNavigationBarTitle({
title: options.course_name
})
}
console.log(this.data);
},
/**

@ -1,2 +1,5 @@
<!--pages/course_detail/course_detail.wxml-->
<text>pages/course_detail/course_detail.wxml</text>
<view class="nav-list">
<navigator url="../classroom/classroom?id={{course.id}}" class="nav">进入教室</navigator>
<navigator url="../exercises/exercises?id={{course.id}}" class="nav">试卷</navigator>
<navigator url="../files/files?id={{course.id}}" class="nav">资源</navigator>
</view>

@ -1 +1,8 @@
/* pages/course_detail/course_detail.wxss */
.nav {
background: white;
border-bottom: 1px solid #eee;
padding: 0 14px;
height: 46px;
line-height: 46px;
}

@ -8,7 +8,8 @@ Page({
loading: true,
page: 1,
show_join_course_modal:false,
},show_join_course_modal: function(event){
},
show_join_course_modal: function(event){
this.setData({show_join_course_modal: true});
},
cancel_join_course_modal: function(event){
@ -28,12 +29,12 @@ Page({
}
console.log(data);
console.log({ ...data });
app.client.join_course({...data})
app.client.join_course(data)
.then(res=>{
console.log(res);
wx.showToast({
title: res.data.message
})
});
wx.navigateTo({
url: "../course_detail/course_detail?course_id="+res.data.course_id
});

@ -4,7 +4,7 @@
<image wx:if="{{courses.length==0 && !loading}}" src="../../images/none2.png" class="none-content"></image>
<text wx:if="{{courses.length==0 && !loading}}" class="none-content">没有可以加入的课程了</text>
<block wx:for="{{courses}}" wx:for-item="course" wx:key="id">
<view hidden="{{course.present}}" bindtap="join_course" class="course-item flex-wrap" data-id="{{course.id}}" data-name="{{course.name}}">
<view hidden="{{course.present}}" bindtap="show_join_course_modal" class="course-item flex-wrap" data-id="{{course.id}}" data-name="{{course.name}}">
<myicon class="course-icon" type="internet_class" size="26"></myicon>
<text class="course-name">{{course.name}}</text>
</view>

@ -16,7 +16,7 @@
position: relative;
}
.course-item:after {
content: '入>';
content: '入>';
display: block;
position: absolute;
right: 2rpx;
@ -35,6 +35,11 @@
.none-content{
align-self: center;
}
view.none-content{
direction: flex;
flex-direction: column;
}
text.none-content{
font-size: 16px;
margin-top: 32rpx;
@ -45,3 +50,14 @@ image.none-content{
height: 160rpx;
width: 180rpx;
}
.code-input{
border-radius: 10rpx;
border: 1rpx solid;
height: 36px;
margin-bottom: 24rpx;
padding-left: 16rpx;
}
lable.identity{
margin-right: 16rpx;
}

@ -1,4 +1,5 @@
<!--pages/createclass/createclass.wxml-->
<view>暂不支持...</view>
<view hidden="{{true}}" class="container">
<text>创建我的课程</text>
<view class="flex-wrap input-wrap">

@ -0,0 +1,181 @@
// pages/exercise/exercise.js
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
exercise_questions: [],
loading: true,
exercise: {}
},
pull_questions: function(){
app.client.start_answer_exercise({exercise_id: this.exercise_id})
.then(res=>{
console.log("pull questions");
console.log(res);
this.setData({ exercise: res.data.exercise});
let questions = res.data.exercise_questions;
for(var i=0;i<questions.length;i++){
if (questions[i]["question_type"]==3){
let null_inputs=[];
for (var j = 1; j<= questions[i]["multi_count"];j++){
var user_answer = questions[i]["user_answer"].filter(answer=>answer.choice_id==j)[0]||{};
console.log(user_answer);
null_inputs.push({choice_id:j, answer_text:user_answer.answer_text||""});
console.log(null_inputs);
}
questions[i]["null_inputs"] = null_inputs;
console.log(questions);
}
}
this.setData({ exercise_questions: questions});
console.log(this.data);
}).catch(console.error)
},
answer_null_question: function ({ detail: { value }, currentTarget: { dataset } }){
console.log("answer_main_question");
console.log(value);
console.log(dataset);
app.client.answer_exercise_question({ question_id: dataset.question_id, exercise_choice_id:dataset.exercise_choice_id, answer_text: value })
.then(res => { console.log("answer_main_question"); console.log(res); })
.catch(error => {
console.error(error);
wx.showToast({
title: error.toString(),
icon: "none"
})
});
},
answer_main_question: function ({ detail: { value }, currentTarget: { dataset }}){
console.log("answer_main_question");
console.log(value);
console.log(dataset);
app.client.answer_exercise_question({ question_id: dataset.question_id, answer_text: value })
.then(res => { console.log("answer_main_question"); console.log(res); })
.catch(error => {
console.error(error);
wx.showToast({
title: error.toString(),
icon: "none"
})
});
},
answer_choice_question: function({detail: {value}, currentTarget: {dataset}}){
console.log("answer_question");
console.log(value);
console.log(dataset);
app.client.answer_exercise_question({ question_id: dataset.question_id, exercise_choice_id: value})
.then(res=>{console.log("answer_question");console.log(res);})
.catch(error=>{
console.error(error);
wx.showToast({
title: error.toString(),
icon: "none"
})
});
},
save_exercise: function({show_loading=true}={}){
if(show_loading){
wx.showLoading({
title: '请稍候',
});
}
app.client.save_exercise({exercise_id: this.exercise_id, complete: wx.hideLoading})
.then(res=>{
console.log("保存答案");
console.log(res);
if(show_loading){
wx.showToast({
title: "保存成功",
});
}
}).catch(console.error)
},
commit_exercise: function(){
wx.showModal({
title: '确认',
content: '交卷后不可更改,确定交卷吗?',
success: res=>{
if(res.confirm){
app.client.save_exercise({ exercise_id: this.exercise_id})
.then(
()=>{
app.client.commit_exercise({exercise_id: this.exercise_id})
.then(res=>{
console.log("交卷");
console.log(res);
wx.navigateBack({
delta:1
})
wx.showToast({
title: res.data.message
})
}).catch(console.error);
}).catch(console.error);
}
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.exercise_id = options.exercise_id;
this.pull_questions();
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
onError: function(e){
console.error(e);
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
this.save_exercise({show_loading: false});
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,73 @@
<view class="container">
<view class="question-list">
<block wx:for="{{exercise_questions}}" wx:for-item="question" wx:key="question_id">
<view class="question">
<text class="hint">第{{question.q_position}}题</text>
<text class="question-title">{{question.question_title}}</text>
<view wx:if="{{question.question_type==0}}">
<radio-group class="choices" bindchange="answer_choice_question" data-question_id="{{question.question_id}}">
<radio disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="choice" wx:for="{{question.question_choices}}" wx:for-item="choice" wx:key="choice_id" checked="{{choice.user_answer_boolean}}" value="{{choice.choice_id}}">
<text class="choice-text">{{choice.choice_text}}</text>
<text wx:if="{{choice.standard_boolean}}" class="error standard-choice">正确答案</text>
</radio>
</radio-group>
</view>
<view wx:elif="{{question.question_type==1}}">
<checkbox-group class="choices" bindchange="answer_choice_question" data-question_id="{{question.question_id}}">
<checkbox disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="choice" wx:for="{{question.question_choices}}" wx:for-item="choice" wx:key="choice_id" checked="{{choice.user_answer_boolean}}" value="{{choice.choice_id}}">
<text class="choice-text">{{choice.choice_text}}</text>
<text wx:if="{{choice.standard_boolean}}" class="error standard-choice">正确答案</text>
</checkbox>
</checkbox-group>
</view>
<view wx:elif="{{question.question_type==2}}">
<radio-group class="choices" bindchange="answer_choice_question" data-question_id="{{question.question_id}}">
<radio disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="choice" wx:for="{{question.question_choices}}" wx:for-item="choice" wx:key="choice_id" checked="{{choice.user_answer_boolean}}" value="{{choice.choice_id}}">
<text class="choice-text">{{choice.choice_text}}</text>
<text wx:if="{{choice.standard_boolean}}" class="error standard-choice">正确答案</text>
</radio>
</radio-group>
</view>
<view wx:elif="{{question.question_type==3}}">
<block wx:for="{{question.null_inputs}}" wx:for-item="null_input">
<view class="null-input flex-wrap">
<text class="hint">填空{{null_input.choice_id}}</text>
<input disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="null-input"
placeholder="输入填空{{null_input.choice_id}}答案"
data-question_id="{{question.question_id}}"
data-exercise_choice_id="{{null_input.choice_id}}"
value="{{null_input.answer_text}}"
bindblur="answer_null_question">
</input>
</view>
</block>
<view wx:if="{{question.standard_answer}}" class="standard-null-inputs">
<view class="standard-null-input flex-wrap" wx:for="{{question.standard_answer}}" wx:for-item="answer">
<text class="hint">第{{answer.choice_id}}空答案:</text>
<text class="error" style="padding-top: 6rpx;">{{answer.answer_text}}</text>
</view>
</view>
</view>
<view wx:elif="{{question.question_type==4}}">
<textarea disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="main-input"
placeholder="输入答案"
bindblur="answer_main_question"
value="{{question.user_answer[0]||''}}"
data-question_id="{{question.question_id}}">
</textarea>
<view wx:if="{{question.standard_answer}}" class="standard-main-input">
<text class="hint">参考答案:</text>
<text class="error">{{question.standard_answer[0]||'暂无'}}</text>
</view>
</view>
<view wx:elif="{{question.question_type==5}}">
<text class="hint">暂不支持实训题...</text>
</view>
</view>
</block>
</view>
</view>
<cover-view wx:if="{{exercise.user_exercise_status!=1 && exercise.user_exercise_status!=4}}" class="foot flex-wrap" >
<button bindtap="save_exercise">保存</button>
<button bindtap="commit_exercise">交卷</button>
</cover-view>

@ -0,0 +1,61 @@
.foot{
position: fixed;
width: 100%;
align-items: center;
background: white;
padding-top: 1px;
border-top: 1rpx solid gray;
bottom: 0;
z-index: 2;
}
.container{
padding-bottom: 40px;
}
.question{
background: white;
margin: 20rpx -6rpx;
padding: 4rpx 20rpx 20rpx 20rpx;
}
.question-title{
display: block;
margin: 5rpx 0rpx 12rpx 0rpx;
}
.choices{
display: flex;
flex-direction: column;
}
.choice{
margin-bottom: 12rpx;
}
.choice-text{
margin-left: 10rpx;
}
.main-input{
height: 120rpx;
margin: 18rpx 0 4rpx 18rpx;
border: 1rpx solid lightgray;
border-radius: 8rpx;
padding-left: 12rpx;
}
view.null-input{
align-items: center;
}
input.null-input{
border: 1rpx solid lightgray;
padding: 14rpx 5rpx;
margin-left: 8rpx;
border-radius: 6rpx;
}
.standard-choice{
margin-left: 24rpx;
}
standard-null-input{
align-items: center;
}

@ -0,0 +1,111 @@
const app = getApp()
Page({
allnavData: [
{
text: "全部",
exercise_status: "all",
course_identities: [2, 5, 6]
},
{
text: "未发布",
exercise_status: 1,
course_identities: [2]
},
{
text: '提交中',
exercise_status: 2,
course_identities: [2, 5, 6]
},
{
text: '已截止',
exercise_status: 3,
course_identities: [2, 5, 6]
},
],
data: {
loading: true,
exercises: [],
navData: [
{
text: "全部",
exercise_status: "all",
course_identities: [2, 5, 6]
},
{
text: '提交中',
exercise_status: 2,
course_identities: [2, 5, 6]
},
{
text: '已截止',
exercise_status: 3,
course_identities: [2, 5, 6]
},
],
currentTab: 0,
navScrollLeft: 0
},
pull_courses_info: function(){
app.client.get_user_info()
.then();
/**@todo */
},
pull_courses: function(){
app.client.search_exercises({ course_id: this.course_id })
.then(res => {console.log("pull_courses");console.log(res); this.setData({ exercises: res.data.exercises, loading: false});console.log(this.data)})
.catch(console.error);
},
see_exercise: function ({ currentTarget: { dataset } }){
wx.navigateTo({
url: '../exercise/exercise?exercise_id=' + dataset.exercise_id,
});
},
enter_exercise: function({currentTarget:{dataset}}){
wx.showModal({
title: '确认',
content: '开始作答吗?',
success: res=>{
if(res.confirm){
wx.navigateTo({
url: '../exercise/exercise?exercise_id='+dataset.exercise_id,
});
}
}
});
},
//事件处理函数
onLoad: function (options) {
this.course_id = options.id;
},
onShow: function(){
this.pull_courses();
},
switchNav(event) {
var cur = event.currentTarget.dataset.current;
//每个tab选项宽度占1/5
var singleNavWidth = this.data.windowWidth / 3;
//tab选项居中
this.setData({
navScrollLeft: (cur - 1) * singleNavWidth
})
if (this.data.currentTab == cur) {
return false;
} else {
this.setData({
currentTab: cur
})
}
},
switchTab(event) {
var cur = event.detail.current;
var singleNavWidth = this.data.windowWidth / 5;
this.setData({
currentTab: cur,
navScrollLeft: (cur - 1) * singleNavWidth
});
},
onPullDownRefresh: function(){
this.pull_courses();
}
})

@ -0,0 +1,4 @@
{
"usingComponents": {},
"enablePullDownRefresh": true
}

@ -0,0 +1,36 @@
<view class="container">
<!-- tab导航栏 -->
<!-- scroll-left属性可以控制滚动条位置 -->
<!-- scroll-with-animation滚动添加动画过渡 -->
<scroll-view scroll-x="true" class="nav" scroll-left="{{navScrollLeft}}" scroll-with-animation="{{true}}">
<block wx:for="{{navData}}" wx:for-index="idx" wx:for-item="navItem" wx:key="idx">
<view class="nav-item {{currentTab == idx ?'active':''}}" data-current="{{idx}}" bindtap="switchNav">
<text>{{navItem.text}}</text>
</view>
</block>
</scroll-view>
<!-- 页面内容 -->
<swiper class="tab-box" current="{{currentTab}}" duration="300" bindchange="switchTab">
<block wx:for="{{navData}}" wx:for-item="navItem" wx:key="exercise_status">
<swiper-item class="tab-content">
<view class="no-content" wx:if="{{exercises.length==0&&!loading}}" class="no-content">
<image class="no-content" src="../../images/none.png" mode="aspectFit"></image>
</view>
<block wx:for="{{exercises}}" wx:for-item="exercise" wx:key="id">
<view class="exercise" wx:if="{{exercise.exercise_status==navItem.exercise_status||navItem.exercise_status=='all'}}" class="exercise" bindlongpress="enter_exercise" data-exercise_id="{{exercise.id}}">
<view class="exercise-name">
<text class="exercise-name">{{exercise.exercise_name}}</text>
</view>
<view class="exercise-info flex-wrap">
<text class="hint" wx:if="{{exercise.exercise_status!=3&&(exercise.current_status==0 || exercise.current_status==2)}}">还有{{exercise.exercise_left_time||' '}}截止</text>
<text class="exercise-tip">{{exercise.exercise_tips[0]}}</text>
<text wx:if="{{exercise.exercise_status!=3&&(exercise.current_status==0 || exercise.current_status==2)}}" class="start-answer tappable" bindtap="enter_exercise" data-exercise_id="{{exercise.id}}">进入答题</text>
<text wx:if="{{(exercise.current_status==1 || exercise.exercise_status==3)&&exercise.current_status!=3}}" class="start-answer tappable" bindtap="see_exercise" data-exercise_id="{{exercise.id}}">查看答题</text>
</view>
</view>
</block>
</swiper-item>
</block>
</swiper>
</view>

@ -0,0 +1,72 @@
.container{
height: 100%;
}
.nav {
height: 85rpx;
width: 100%;
box-sizing: border-box;
overflow: hidden;
line-height: 70rpx;
font-size: 16px;
white-space: nowrap;
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
.nav-item {
width: 25%;
display: inline-block;
text-align: center;
}
.active{
color: green;
border-bottom: 3rpx solid green;
}
.tab-box{
padding-top: 85rpx;
height: 100%;
box-sizing: border-box;
}
.tab-content{
overflow-y: scroll;
width: 100%;
}
.tappable{
color: #1aad19;
padding: 0 12px;
}
text.start-answer{
position: fixed;
right: 8rpx;
}
.exercise{
background: white;
padding: 17rpx 12rpx;
margin: 14rpx 0rpx;
}
.exercise-info{
margin-top: 4rpx;
align-items: center;
}
.exercise-tip{
color: white;
font-size: 10px;
height: 14px;
background: lightblue;
border-radius: 14rpx;
padding: 4rpx 16rpx;
margin-left: 18rpx;
}
view.no-content{
display: flex;
flex-direction: column;
}
image.no-content{
width: 300rpx;
height: 300rpx;
}

@ -0,0 +1,108 @@
// pages/files/files.js
const app = getApp();
const base_url = "https://www.educoder.net";
Page({
/**
* 页面的初始数据
*/
data: {
files: [],
loading: true
},
pull_files:function(){
wx.showLoading({
title: '加载中',
})
app.client.get_course_files({course_id : this.course_id, complete: ()=>{wx.hideLoading();this.setData({loading: false})}})
.then(res=>{
console.log("pull_files");
console.log(res);
this.setData({files: res.data.data.files});
})
.catch(console.error);
},
download:function({currentTarget:{dataset}}){
const {url, id} = dataset;
wx.showLoading({
title: '下载中',
})
wx.downloadFile({
url: base_url + url,
success: (res)=> {
wx.openDocument({
filePath: res.tempFilePath,
fail: console.error
});
},
fail: function(error) {wx.showToast({
title: error.toString(),
icon:"none"
});
console.error(error);
},
complete: function (res) {
wx.hideLoading();
},
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.course_id = options.id;
console.log(this.course_id);
this.pull_files();
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

@ -0,0 +1,18 @@
<view class="container">
<text>课堂资源</text>
<view class="no-file-view">
<image wx:if="{{files.length==0 && !loading}}" src="../../images/none2.png" class="no-file"></image>
</view>
<view class="file-list form-wrap">
<block wx:for="{{files}}" wx:for-item="file" wx:key="objectId">
<image wx:if="{{file.ispic}}" src="{{file.fileid}}" bindtap="preview_pic" data-fileid="{{file.fileid}}"></image>
<view class="file-item flex-wrap" bindtap="{{file.ispic?'preview_pic':'download'}}" data-id="{{file.id}}" data-url="{{file.url}}">
<text>{{file.title}}</text>
<text class="hint file-uploader">上传者:{{file.author.name}}</text>
</view>
</block>
</view>
</view>
<view wx:if="{{false}}" class="upload-file foot">
<button type="primary" bindtap="upload">上传文件资源</button>
</view>

@ -0,0 +1,48 @@
/* pages/classdetail/classdetail.wxss */
.file-list{
display: flex;
flex-direction: column;
margin: 0 -12px;
margin-bottom: 40px;
}
.file-item{
background: white;
border-bottom: 1px solid #eee;
padding: 16rpx 16px;
position: relative;
}
.file-item text{
vertical-align: middle;
}
.file-uploader{
font-size: 10px;
}
.foot{
width: 100%;
position: fixed;
bottom: 0;
}
button{
margin: 0px 36px;
vertical-align: center;
font-size: 14px;
}
.no-file-view{
width: 100%;
flex-direction: column;
display: flex;
}
text.no-file{
font-size: 16px;
margin-top: 32rpx;
vertical-align: center;
}
image.no-file{
margin-top: 120rpx;
height: 160rpx;
width: 180rpx;
vertical-align: center;
}

@ -11,16 +11,36 @@ Page({
login: "",
password: ""
},
save_input:function(){
wx.setStorage({
key: 'login',
data: this.data.login,
})
},
load_input:function(){
wx.getStorage({
key: 'login',
success: res => {
console.log(res);
this.setData({login: res.data});
},
})
},
update_login:function({detail: {value}}){
this.setData({login: value});
},
update_password: function({detail: {value}}){
this.setData({password: value});
},
login: function({currentTarget:{dataset}}){
login_test: function(){
this.setData({login: "educoder_weapp@126.com", password: "abcdefgh"});
this.login()
},
login: function(){
const {login, password} = this.data;
app.client.login({login: login, password: password, autologin: 1,
success(res){
success:res=>{
this.save_input();
wx.navigateBack({
delta: 1
})
@ -38,7 +58,7 @@ Page({
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.load_input();
},
/**

@ -6,6 +6,7 @@
<view class="input-wrap">
<input class="login-input"
bindinput="update_login"
value="{{login}}"
placeholder="用户名、邮箱、手机号">
</input>
</view>
@ -14,11 +15,14 @@
<input password
class="login-input"
placeholder="密码"
bindinput="update_password">
value="{{password}}"
bindinput="update_password"
bindconfirm="login">
</input>
</view>
</view>
<button class="login-submit" type="primary" bindtap="login">
<button class="login-submit" type="primary" bindtap="login" bindlongpress="login_test">
登陆
</button>
<button hidden="{{true}}" class="login-submit" type="primary" bindtap="login_test">登陆测试账号</button>
</view>

@ -0,0 +1,139 @@
// pages/mark_detail/mark_detail.js
const app = getApp();
const AV = require("../../lib/av-live-query-weapp-min");
const {jsonify} = require("../../utils/leancloudutils")
Page({
/**
* 页面的初始数据
*/
students_login_name: {},
data: {
grades: [],
loading: true,
exercises: [],
navData: [
{
text: "全部",
login: "*"
},
{
text: '我的',
login: app.client.current_user.login
},
],
currentTab: 0,
navScrollLeft: 0
},
//@todo: 退出课堂姓名的获取??
pull_students:function(){
//@todo limit20=>solve
return app.client.get_course_students({course_id: this.course_id})
.then(res=>{
let students = res.data.students;
for(var student of students){
this.students_login_name[student.login] = student.name;
}
console.log(this.students_login_name);
})
},
pull_grades: function(){
let query = new AV.Query("Grade");
query.equalTo("edu_course_id", this.course_id);
return query.find().then(grades=>{
console.log(grades);
console.log(this.students_login_name);
grades = grades.filter(grade=>{console.log(grade.edu_account_login);return grade.edu_account_login in this.students_login_name});
grades = grades.map(grade=>{
grade.set("name", this.students_login_name[grade.edu_account_login]);
grade = grade.toJSON();
grade["time"]=grade["createdAt"].slice(0, 10);
return grade;
});
this.setData({grades});
console.log(this.data);
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.course_id = options.course_id;
this.course_id = "3518"
console.log(this.course_id);
this.pull_students().then(this.pull_grades);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
switchNav(event) {
var cur = event.currentTarget.dataset.current;
//每个tab选项宽度占1/5
var singleNavWidth = this.data.windowWidth / 3;
//tab选项居中
this.setData({
navScrollLeft: (cur - 1) * singleNavWidth
})
if (this.data.currentTab == cur) {
return false;
} else {
this.setData({
currentTab: cur
})
}
},
switchTab(event) {
var cur = event.detail.current;
var singleNavWidth = this.data.windowWidth / 5;
this.setData({
currentTab: cur,
navScrollLeft: (cur - 1) * singleNavWidth
});
}
})

@ -0,0 +1,4 @@
{
"usingComponents": {},
"navigationBarTitleText": "分数详情"
}

@ -0,0 +1,29 @@
<view class="container">
<!-- tab导航栏 -->
<!-- scroll-left属性可以控制滚动条位置 -->
<!-- scroll-with-animation滚动添加动画过渡 -->
<scroll-view scroll-x="true" class="nav" scroll-left="{{navScrollLeft}}" scroll-with-animation="{{true}}">
<block wx:for="{{navData}}" wx:for-index="idx" wx:for-item="navItem" wx:key="idx">
<view class="nav-item {{currentTab == idx ?'active':''}}" data-current="{{idx}}" bindtap="switchNav">
<text>{{navItem.text}}</text>
</view>
</block>
</scroll-view>
<!-- 页面内容 -->
<swiper class="tab-box" current="{{currentTab}}" duration="300" bindchange="switchTab">
<block wx:for="{{navData}}" wx:for-item="navItem" wx:key="exercise_status">
<swiper-item class="tab-content">
<view class="grade-list">
<block wx:for="{{grades}}" wx:for-item="grade" wx:key="objectId">
<view wx:if="{{grade.edu_account_login==navItem.login||navItem.login=='*'}}" class="grade flex-wrap">
<text class="name">{{grade.name}}</text>
<text class="time">{{grade.time}}</text>
<text class="{{grade.mark<0?'mark delete':'mark add'}}">{{grade.mark}}</text>
</view>
</block>
</view>
</swiper-item>
</block>
</swiper>
</view>

@ -0,0 +1,68 @@
.container{
height: 100%;
}
.nav {
height: 85rpx;
width: 100%;
box-sizing: border-box;
overflow: hidden;
line-height: 70rpx;
font-size: 16px;
white-space: nowrap;
position: fixed;
top: 0;
left: 0;
z-index: 99;
}
.nav-item {
width: 33%;
display: inline-block;
text-align: center;
}
.active{
color: green;
border-bottom: 3rpx solid green;
}
.tab-box{
padding-top: 85rpx;
height: 100%;
box-sizing: border-box;
}
.tab-content{
overflow-y: scroll;
width: 100%;
}
.grade{
background: white;
padding: 20rpx 10rpx;
border-bottom: 1rpx solid gray;
}
.grade text{
margin: 0rpx 20rpx;
}
.time{
position: fixed;
right: 180rpx;
}
.mark{
position: fixed;
right: 3rpx;
padding: 3rpx 23rpx;
width: 45rpx;
text-align: center;
}
.add{
color: white;
background: green;
border-radius: 12rpx;
}
.delete{
color: white;
background: red;
border-radius: 12rpx;
}

@ -3,6 +3,7 @@ const login = require("../../model/user");
const AV = require("../../lib/av-live-query-weapp-min.js");
const { jsonify } = require('../../utils/leancloudutils');
// pages/class/class.js
const app = getApp();
const getDataForRender = class_ => ({
name: class_.get('name'),
@ -18,59 +19,69 @@ Page({
class.name 课程名称
*/
data: {
classes: [],
courses: [],
loading: true,
},
presences: [],
classes: [],
add_class:function(event){
wx.navigateTo({
url: '../addclass/addclass',
})
show_join_course_modal: function (event) {
this.setData({ show_join_course_modal: true });
},
cancel_join_course_modal: function (event) {
this.setData({ show_join_course_modal: false });
},
update_invite_code: function ({ detail: { value } }) {
this.setData({ invite_code: value });
},
del_class: function(event){
class_id = event.currentTarget.dataset.class_id;
class_name = event.currentTarget.dataset.class_name;
presence = this.presences.filter(presence=>presence.get("class").id==class_id)[0];
if(presence==null){
console.warn("presence not in list, is it the teacher's classroom?")
return;
update_identities: function ({ detail: { value } }) {
this.setData({ identities: value })
},
join_course: function (event) {
const { invite_code, identities } = this.data;
let data = { invite_code: invite_code };
for (var identity of identities) {
data[identity] = 1;
}
pull_presences = this.pull_presences.bind(this);
wx.showModal({
title: '退出学习',
content: '退出学习会清零你该门课程的分数',
success(res) {
if (res.confirm) {
wx.showLoading({
title: '请稍候',
})
presence.destroy().then(() => {
pull_presences();
wx.hideLoading();
console.log(data);
console.log({ ...data });
app.client.join_course({ ...data })
.then(res => {
console.log(res);
wx.showToast({
title: '退出成功',
icon: "success"
title: res.data.message
})
},
() => {
wx.hideLoading();
wx.navigateTo({
url: "../course_detail/course_detail?course_id=" + res.data.course_id
});
this.cancel_join_course_modal();
})
.catch(error => {
wx.showToast({
title: '操作失败',
title: error.toString(),
icon: "none"
});
console.warn(error);
})
}).catch(error => console.error(error.message));
} } });
},
enter_class: function(event){
enter_course: function(event){
console.log(event);
var class_id = event.currentTarget.dataset.class_id;
var class_name = event.currentTarget.dataset.class_name;
let {id, course_name} = event.currentTarget.dataset;
wx.navigateTo({
url: "../classroom/classroom?class_id="+class_id+"&"+"class_name="+class_name,
url: "../course_detail/course_detail?id="+id+"&course_name="+course_name,
})
},
pull_courses: function(event){
app.client.get_user_courses({complete:()=>{console.log("pull_courses complete!!!!!!");this.setData({loading:false})}})
.then(res=>{
console.log("pull_courses");
console.log(res);
this.setData({courses: res.data.courses});
}).catch(console.error);
console.log(this.data);
},
/**
* 生命周期函数--监听页面加载
*/
@ -85,36 +96,12 @@ Page({
},
pull_presences: function(){
console.log("classes.pull_presences");
var query = new AV.Query("Presence");
query.equalTo("user", AV.User.current());
query.include("class");
return query.find().then((presences) => {
this.presences = presences;
console.log(presences);
let classes = presences.map(presence => {return presence.get("class")});
console.log(classes);
query = new AV.Query("Class_");
query.equalTo("teacher", AV.User.current());
query.include("teacher");
query.find().then(myclasses=>{
this.setData(jsonify({classes: classes.concat(myclasses), loading: false}));
})
}).catch(console.error);
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log("classes.onShow()");
if(this.data.loading){
wx.showLoading({
title: '加载中',
})
}
this.pull_presences().then(wx.hideLoading);
this.pull_courses();
},
/**
@ -135,7 +122,7 @@ Page({
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
this.pull_presences();
this.pull_courses();
},
/**

@ -1,23 +1,26 @@
<!--
所有的页面数据见同目录classes.js中Page.data定义部分
classes: 课程列表 type: Array
元素class: 课程信息 class.objectId 唯一
class.objectId 唯一键
class.name 课程名称
-->
<view class="container">
<view class="course-list">
<image wx:if="{{classes.length==0 && !loading}}" class="none-content" src="../../images/none.png" mode="aspectFit"></image>
<text wx:if="{{classes.length==0 && !loading}}" class="none-content hint">你的课程表空空如也</text>
<block wx:for="{{classes}}" wx:for-item="class" wx:key="objectId">
<view class="classroom flex-wrap" data-class_id="{{class.objectId}}" data-class_name="{{class.name}}" bindtap="enter_class" catchlongpress="del_class">
<view wx:if="{{courses.length==0 && !loading}}" class="none-content">
<image class="none-content" src="../../images/none.png" mode="aspectFit"></image>
<text class="none-content hint">你的课程空空如也</text>
</view>
<block wx:for="{{courses}}" wx:for-item="course" wx:key="id">
<view class="classroom flex-wrap" data-id="{{course.id}}" data-course_name="{{course.name}}" bindtap="enter_course">
<!--icon type="success"></icon-->
<myicon class="classroom-icon" type="internet_class" size="26" color="#2351e4"></myicon>
<text>{{class.name}}</text>
<text>{{course.name}}</text>
</view>
</block>
</view>
</view>
<myicon class="add-class" type="add" color="#00C7B7" size="56" bindtap="add_class"></myicon>
<myicon class="add-class" type="add" color="#00C7B7" size="56" bindtap="show_join_course_modal"></myicon>
<modal id="modal" hidden="{{!show_join_course_modal}}" title="加入课堂" confirm-text="提交" cancel-text="取消" bindcancel="cancel_join_course_modal" bindconfirm="join_course">
<input type='text' bindinput="update_invite_code" class="code-input" placeholder="邀请码" auto-focus/>
<checkbox-group bindchange="update_identities">
<text>身份:</text>
<lable class="identity"><checkbox value="professor"/>教师</lable>
<lable class="identity"><checkbox value="assistant_professor"/>助教</lable>
<lable class="identity"><checkbox value="student"/>学生</lable>
</checkbox-group>
</modal>

@ -28,12 +28,12 @@
.classroom text {
vertical-align: middle;
margin-right: 160rpx
}
.classroom-icon{
margin-left: 2px;
margin-right: 10px;
}
.add-class{
@ -60,3 +60,15 @@ image.none-content{
.add-class:hover{
opacity: 0.6;
}
.code-input{
border-radius: 10rpx;
border: 1rpx solid;
height: 36px;
margin-bottom: 24rpx;
padding-left: 16rpx;
}
lable.identity{
margin-right: 16rpx;
}

@ -66,10 +66,15 @@ Page({
},
onShow: function(){
app.client.get_user_info()
.then(res=>{
console.log("get_user_info");
console.log(res)
this.setData({current_user: app.client.current_user})
if ("image_url" in app.client.current_user && app.client.current_user.image_url){
this.setData({avatar_url: "https://www.educoder.net/images/" + app.client.current_user.image_url})
if ("image_url" in app.client.current_user && app.client.current_user.image_url) {
this.setData({ avatar_url: "https://www.educoder.net/images/" + app.client.current_user.image_url })
}
})
}
// enter_usersetting: function(event){

@ -8,7 +8,7 @@
<!--navigator url="../user/user" class="nav user" bindlongpress="enter_changeuser">登陆信息修改</navigator>
<navigator hidden="{{true}}" url="../changeuser/changeuser" class="nav user">更换登陆用户</navigator-->
<navigator class="nav addclass" bindtap="show_join_course_modal">加入课程</navigator>
<navigator url="../createclass/createclass" class="nav createclass">创建课程</navigator>
<navigator hidden="{{true}}" url="../createclass/createclass" class="nav createclass">创建课程</navigator>
<navigator url="../about/about" class="nav about">关于</navigator>
</view>
<button class="login" type="primary" wx:if="{{current_user.user_id==2}}" bindtap="enter_login">登陆</button>

@ -46,6 +46,7 @@
border: 1rpx solid;
height: 36px;
margin-bottom: 24rpx;
padding-left: 16rpx;
}
lable.identity{
margin-right: 16rpx;

Loading…
Cancel
Save