使用educoderAPI

smart_class
educoder_weapp 5 years ago
parent 083406bb74
commit c795112f0a

@ -10,7 +10,9 @@
- 学员可以收到教员让其起立提问、回答的提示,还可以点击“我要提问、回答”
- 在课堂界面右下角进入“更多”可以查看本课堂的课程文件资源
- 课堂内有讨论区,可以交流
- 在课堂界面右下角进入“资源”可以查看本课堂的课程文件资源 # 发布版要长按白色底部栏进入
- 教员可以在课程的设置界面中更新课程的名称,还可以将学员移除本课程的学习

@ -1,37 +1,72 @@
//app.js
//导入leancloud库与后台交互
import {Session} from "./data/requests";
import {Client} from "./data/client";
import {Account, Course, Exercise, ExerciseQuestion} from "./data/eduapi"
const AV = require('./lib/av-live-query-weapp-min');
const Towxml = require('/towxml/main');
const login = require("./model/user");
//初始化
AV.init({
appId: 'eVHYNBdT5D2lDxNj5jtJXsWT-MdYXbMMI',
appKey: 'waM3bwf1ftpsMLjRBqqVyJIQ',
appId: 'eVHYNBdT5D2lDxNj5jtJXsWT-MdYXbMMI',
appKey: 'waM3bwf1ftpsMLjRBqqVyJIQ',
});
// test Appid
// appId: 'fQCxN98zS5thYY3AceKdI8Pj-MdYXbMMI',
// appKey: 'Tdi1DcLlVYrTabFiBaA00pjj',
App({
config: {
host: 'wsw1999.xyz'
towxml: new Towxml(),
client: new Client(),
string_format_init: function(){
//使String类实现format方法
//@todo: 待测试
String.prototype.format = function (kwargs) {
return this.replace(/\{(\w+)\}/g, function (k, v) {
return kwargs[v]
});
};
},
enter_login: function(){
wx.navigateTo({
url: "/pages/login/login"
});
},
onLaunch () {
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'
})
onLaunch: function () {
console.log("onLauch");
console.log(this.client.get_user_info({
success: res=>{
console.log("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");
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,6 @@
{
"pages": [
"pages/classes/classes",
"pages/my_courses/my_courses",
"pages/setting/setting",
"pages/changeuser/changeuser",
"pages/user/user",
@ -9,7 +9,11 @@
"pages/classroom/classroom",
"pages/classsetting/classsetting",
"pages/about/about",
"pages/createclass/createclass"
"pages/createclass/createclass",
"pages/login/login",
"pages/test/test",
"pages/courses/courses",
"pages/course_detail/course_detail"
],
"window": {
"backgroundTextStyle": "dark",
@ -22,8 +26,14 @@
"selectedColor": "#00C7B7",
"list": [
{
"pagePath": "pages/classes/classes",
"text": "学习",
"pagePath": "pages/my_courses/my_courses",
"text": "我的课堂",
"iconPath": "images/tabbar-icon/tabbar_study_default.png",
"selectedIconPath": "images/tabbar-icon/tabbar_study_pressed.png"
},
{
"pagePath": "pages/courses/courses",
"text": "课程列表",
"iconPath": "images/tabbar-icon/tabbar_contact_default.png",
"selectedIconPath": "images/tabbar-icon/tabbar_contact_pressed.png"
},

@ -1,7 +1,7 @@
<!--components/icon/myicon.wxml-->
<view
class="custom-class iconfont myicon-{{ type }}"
style="{{ color ? 'color: ' + color : '' }}; {{ size ? 'font-size: ' + size + 'px' : '' }}"
style="{{ color ? 'color: ' + color + ';' : '' }}{{ size ? 'font-size: ' + size + 'px;' : '' }}"
bind:tap="onClick">
<view wx:if="{{ info !== null }}" class="myicon__info">{{ info }}</view>
</view>

@ -0,0 +1,23 @@
// components/modal/join_course/join_course.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})

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

@ -0,0 +1,10 @@
<!--components/modal/join_course/join_course.wxml-->
<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>

@ -0,0 +1,9 @@
.code-input{
border-radius: 10rpx;
border: 1rpx solid;
height: 36px;
margin-bottom: 24rpx;
}
lable.identity{
margin-right: 16rpx;
}

@ -0,0 +1,182 @@
import {Account, Course} from "./eduapi"
import {Session} from "./requests";
import {Cookie} from "./cookie";
/**
* 客户端类其method实现客户端各种操作将接口Promise化从而使其调用更加方便简洁
* 要在此处实现网络数据及cookie的缓存
*/
export class Client{
constructor({session}={}){
if(!session) {
this.session = new Session();
}else {
this.session = session;
}
this.load_cached_cookies();
this.current_user = {};
console.log(this.session);
}
load_cached_cookies(){
try {
var value = wx.getStorageSync('_educoder_session');
if (value) {
this.session.set_cookie(new Cookie(value))
}
var value = wx.getStorageSync("autologin_trustie");
if (value) {
this.session.set_cookie(new Cookie(value));
}
console.log("read cookies");
console.log(this.session.cookies);
} catch (e) {
// Do something when catch error
console.log("there is not cachede cookie")
console.error(e);
}
}
save_cookies(){
for(var cookie of Object.values(this.session.cookies)){
console.log("client save cookie");
console.log(cookie);
cookie.save();
}
}
require_login(){
wx.redirectTo({
url: "../pages/login/login"
});
wx.showToast({
title:"请先登陆",
icon: "none",
duration: 4000
});
}
login({login, password, autologin, success, fail, complete}){
return new Promise((resolve, reject) => {
Account.login({
session: this.session, login: login, password: password, autologin: autologin,
fail: error => {
if(typeof fail == "function") {
fail(error);
}
reject(error);
},
complete: complete,
success: res => {
this.save_cookies();
this.current_user = {...this.current_user, ...res.data};
this.get_user_info();
if (typeof success == "function") {
success(res);
}
resolve(res);
}
});
});
}
logout({success, fail, complete}={}){
return new Promise((resolve, reject) => {
Account.logout({session: this.session,
success: res=>{
if(typeof success == "function") {
success(res);
}
this.get_user_info();
resolve(res);
}, fail: error=>{
if(typeof fail =="function"){
fail(error);
}
reject(error);
}, complete: complete});
})
}
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};
if(typeof success == "function"){
success(res);
}
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
})
});
}
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_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) => {
Course.search({session: this.session, page: page, order: order, search: search, complete: complete,
success: res=>{
if(typeof success == "function"){
success(res);
}
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
});
});
}
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,
success: res=>{
if(typeof success == "function"){
success(res);
}
resolve(res);
},
fail: error=>{
if(typeof fail == "function"){
fail(error);
}
reject(error);
}
})
});
}
search_exercise(){}
start_answer_exercise(){}
answer_exercise_question(){}
}

@ -0,0 +1,45 @@
/**
* Cookie类用于网络中cookie的各类操作
*/
export class Cookie{
/**
*
* example: "autologin_trustie=8acaa2b09d5056c0e9d82519052276b9d4a524e9; domain=.educoder.net ; path=/; expires=Fri, 29 Nov 2019 15:32:53 -0000; HttpOnly"
*/
constructor(str){
this.origin_str = str;
this.analyse_cookie(str);
}
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;
//return this.key + "=" + this.value;
}
save(){
if(!this.key){
throw new Error("没有键值");
}
wx.setStorageSync(this.key, this.origin_str);
}
static load(key){
return new Cookie(wx.getStorageSync(key));
}
}
function test() {
//used to test the class Cookie
cookie_str = "autologin_trustie=8acaa2b09d5056c0e9d82519052276b9d4a524e9; domain=.educoder.net ; path=/; expires=Fri, 29 Nov 2019 15:32:53 -0000; HttpOnly";
cookie = new Cookie(cookie_str);
}
//test();

@ -0,0 +1,213 @@
const api_base_url = "https://www.educoder.net/api";
/**
* https://www.educoder.net的api接口通过其实现用户与后端进行交互
*/
export class Account{
static login({session, login, password, autologin, success, fail, complete}) {
console.log("login");
let data = {login: login, password: password, autologin: autologin};
session.request({
url: api_base_url + "/accounts/login.json",
method: "POST",
data: data,
header: {"content-type": "application/json"},
success: (res)=>{
if("status" in res.data && res.data.status<0){
fail(new Error(res.data.message));
return;
}
console.log("type of success:"+ typeof success);
if(typeof success == "function") {
success(res);
}
},
fail: fail,
complete: complete
});
}
static get_user_info({session, success, fail, complete}){
let data = {school: 1}
session.request({
url: api_base_url + "/users/get_user_info.json",
method: "GET",
data: data,
success: success,
fail: fail,
complete: complete
})
}
static get_verification_code({session, login, type, success, fail, complete}){
let data = {login: login, type: type};
//@notice type: 验证码用途 type=1=> 注册 type=2 => 重置密码
session.request({
url: api_base_url + "/accounts/get_verification_code.json",
method: "GET",
data: data,
success: success,
fail: fail,
complete: complete
})
}
static register({session, login, password, code, success, fail, complete}){
let data = {login: login, password: password, code: code};
session.request({
url: api_base_url + "/accounts/register.json",
method: "POST",
data:data,
success(res) {
if("status" in res.data && res.data.status<0){
fail(new Error(res.data.message));
return;
}
success(res);
},
fail: fail,
complete: complete
})
}
static attendance({session, success, fail, complete}){
session.request({
url: api_base_url + "/users/attendance.json",
success(res) {
if("status" in res.data && res.data.status<0){
fail(new Error(res.data.status));
return;
}
if(typeof success == "function"){
success(res);
}
},
fail: fail,
complete: complete
})
}
static logout({session, success, fail, complete}){
session.request({
url: api_base_url + "/accounts/logout.json",
method: "GET",
success: success,
fail: fail,
complete: complete
})
}
}
export class Course{
static create({session, data, success, fail, complete}){
}
static search({session, limit=20, page=1, order="all", search="", success, fail, complete}){
let data = {limit: limit, page: page, order: order, search: search};
return session.request({
url: api_base_url + "/courses.json",
method: "GET",
data: data,
success: success,
fail: fail,
complete: complete
})
}
static join({session, invite_code, professor=null,assistant_professor=null,student=null, success, fail, complete}){
let data = {
invite_code: invite_code,
professor: professor,
assistant_professor: assistant_professor,
student: student
};
return session.request({
url: api_base_url + "/courses/apply_to_join_course.json",
method:"POST",
data: data,
success: res=>{
if("status" in res.data && res.data.status<0){
fail(new Error(res.data.message));
return;
}
if(typeof success == "function"){
success(res);
}
},
fail: fail,
complete: complete
})
}
static get_user_info({session, course_id, success, fail, complete}){
let data = {course_id: course_id, school: 1}
return session.request({
url: api_base_url + "/users/get_user_info.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,
sort: sort,
page: page,
limit: limit,
course_group_id: course_group_id
};
return session.request({
url: api_base_url + "/courses/" + course_id + "/students.json",
method: "GET",
data: data,
success(res){
if("status" in res.data && "message" in res.data){
fail(new Error(res.data.message));
return;
}
success(res);
},
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",
method: "GET",
data: data,
success: success,
fail:fail,
complete: complete
})
}
static start_answer({session, exercise_id, login, success, fail, complete}){
let data = {login: login};
return session.request({
url: api_base_url + "/exercises/" + exercise_id + "/start_answer.json",
method: "GET",
data: data,
success: success,
fail: fail,
complete: complete
})
}
}
export class ExerciseQuestion {
static answer({session, question_id, exercise_choice_id, login, success, fail, complete}){
let data = {exercise_choice_id: exercise_choice_id};
return session.request({
url: api_base_url + "/exercise_questions/" + question_id +"/exercise_answer.json",
method: "POST",
data: data,
success: success,
fail: fail,
complete: complete
})
}
}
export class Ui{
}

@ -0,0 +1,72 @@
import {Cookie} from "./cookie";
/**
* 微信网络请求接口的封装使其能够支持简单的cookie保存发送功能
*/
export class Session {
cookies = {}
constructor(){
}
set_cookie(cookie){
this.cookies[cookie.key] = cookie;
}
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}) {
return wx.request({
url: url,
data: data,
header: {...header, "Cookie": this.cookie_str},
method: method,
dataType: dataType,
responseType: responseType,
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]));
}
} else {
console.log("request.js: no cookies in this request");
}
//console.log(this.cookies);
if (typeof success == "function") {
success(res);
} else {
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({
url: url,
filePath: filePath,
name: name,
header: {...header, "content-type": "multipart/form-data", "Cookie": this.cookie_str},
formData: formData,
success: success,
fail: fail,
complete: complete
})
}
downloadFile({url, header, filePath, success, fail, complete}){
return wx.downloadFile({
url: url,
header: {...header, "Cookie": this.cookie_str},
filePath: filePath,
success: success,
fail: fail,
complete: complete
})
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -1,18 +1,26 @@
// pages/about/about.js
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
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.',
data: {
article: {}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
const _ts = this;
let data = app.towxml.toJson(this.md,'markdown');
_ts.setData({
article: data
});
},
/**

@ -1,24 +1,4 @@
<import src="/towxml/entry.wxml"/>
<view class="container">
<text>
# 功能介绍
- 学员可以在点击右下角”加入课堂”选择课程加入,教员可以在“加入课堂中”新建课程
- 长按相应课程可以退出学习
- 进入课堂界面会显示在位,头像为彩色,若退出课堂界面则会显示灰色头像
- 教员在课堂界面中可以直观地看到学员在位情况,可以选择学员让其起立回答问题,并且对学员可以进行加分、减分操作
- 学员可以收到教员让其起立提问、回答的提示,还可以点击“我要提问、回答”
- 在课堂界面右下角进入“更多”可以查看本课堂的课程文件资源
- 教员可以在课程的设置界面中更新课程的名称,还可以将学员移除本课程的学习
## 其他
- 用户可以在设置中更改姓名、用户名
</text>
<template is="entry" data="{{...article}}" class="about"/>
</view>

@ -1 +1,17 @@
/* pages/about/about.wxss */
/**基础风格样式**/
@import '/towxml/style/main.wxss';
/**如果页面有动态主题切换,则需要将使用到的样式全部引入**/
/**主题配色(浅色样式)**/
@import '/towxml/style/theme/light.wxss';
/**主题配色(深色样式)**/
@import '/towxml/style/theme/dark.wxss';
.about{
padding-bottom: 4px;
}

@ -1,12 +1,12 @@
<!--pages/addclass/addclass.wxml-->
<view class="container">
<view class="class-list form-wrap">
<view class="course-list form-wrap">
<image wx:if="{{classes.length==0 && !loading}}" src="../../images/none2.png" class="none-content"></image>
<text wx:if="{{classes.length==0 && !loading}}" class="none-content">没有可以加入的课程了</text>
<block wx:for="{{classes}}" wx:for-item="class" wx:key="objectId">
<view hidden="{{class.present}}" bindtap="add_class" class="class-item flex-wrap" data-id="{{class.objectId}}" data-name="{{class.name}}">
<myicon class="class-icon" type="internet_class" size="26"></myicon>
<view hidden="{{class.present}}" bindtap="add_class" class="course-item flex-wrap" data-id="{{class.objectId}}" data-name="{{class.name}}">
<myicon class="course-icon" type="internet_class" size="26"></myicon>
<text>{{class.name}}</text>
</view>
</block>

@ -1,21 +1,21 @@
/* pages/addclass/addclass.wxss */
.class-icon{
.course-icon{
margin-left: 2px;
margin-right: 12px;
}
.class-list{
.course-list{
display: flex;
flex-direction: column;
margin: 0 -12px
}
.class-item{
.course-item{
align-items: center;
background: white;
padding: 30rpx 12px;
border-bottom: 1rpx solid #EEE;
position: relative;
}
.class-item:after {
.course-item:after {
content: '加入 >';
display: block;
position: absolute;
@ -27,7 +27,7 @@
margin-right: 30rpx;
color: #999;
}
.class-item text{
.course-item text{
vertical-align: middle;
}

@ -7,7 +7,7 @@ Page({
/**
* 页面的初始数据
*/
users: null,
users: [],
data: {
current_user: {},
users: []
@ -39,19 +39,22 @@ Page({
}).catch(error=>console.error(error.message));
},
pull_users: function(){
pull_users: function(limit){
this.setData(jsonify({ current_user: AV.User.current() }));
query = new AV.Query("User");
query.limit(limit);
query.ascending('createdAt');
query.skip(this.users.length);
return query.find().then((users) => {
this.users = users;
this.setData(jsonify({ users }));
this.users = this.users.concat(users);
this.setData(jsonify({ users: this.users}));
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.pull_users()
this.pull_users(15);
},
/**
@ -86,14 +89,16 @@ Page({
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
this.pull_users();
this.users = [];
this.pull_users(50);
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
console.log("onReachBottom")
this.pull_users(50);
},
/**

@ -74,6 +74,7 @@ movable-view{
.class-detail{
right: 0;
}
.class-setting{
left:0;
}

@ -0,0 +1,66 @@
// pages/course_detail/course_detail.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

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

@ -0,0 +1,2 @@
<!--pages/course_detail/course_detail.wxml-->
<text>pages/course_detail/course_detail.wxml</text>

@ -0,0 +1 @@
/* pages/course_detail/course_detail.wxss */

@ -0,0 +1,108 @@
// pages/courses/courses.js
const app = getApp();
Page({
data: {
courses: [],
loading: true,
page: 1,
show_join_course_modal:false,
},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});
},
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;
}
console.log(data);
console.log({ ...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
});
this.cancel_join_course_modal();
})
.catch(error=>{
wx.showToast({
title: error.toString(),
icon: "none"
});
console.warn(error);
})
},
fetch_courses: function(options){
return app.client.search_courses(options)
},
set_courses: function(courses){
this.setData({courses: courses});
},
add_courses: function(courses){
this.setData({
courses:[...this.data.courses, ...courses],
})
},
onLoad: function (options) {
this.fetch_courses().then(res=>{
console.log(res);
this.set_courses(res.data.courses);
})
},
onReady: function () {
},
onShow: function () {
},
onHide: function () {
},
onUnload: function () {
},
onPullDownRefresh: function () {
},
onReachBottom: function () {
this.fetch_courses({ page: this.data.page + 1 })
.then(res => {
this.setData({ page: this.data.page + 1 })
this.add_courses(res.data.courses);
})
},
onShareAppMessage: function () {
}
})

@ -0,0 +1,5 @@
{
"usingComponents": {
"myicon": "/components/icon/myicon"
}
}

@ -0,0 +1,24 @@
<!--pages/addclass/addclass.wxml-->
<view class="container">
<view class="course-list form-wrap">
<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}}">
<myicon class="course-icon" type="internet_class" size="26"></myicon>
<text class="course-name">{{course.name}}</text>
</view>
</block>
</view>
</view>
<!--components/modal/join_course/join_course.wxml-->
<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>

@ -0,0 +1,47 @@
/* pages/addclass/addclass.wxss */
.course-icon{
margin-left: 2px;
margin-right: 12px;
}
.course-list{
display: flex;
flex-direction: column;
margin: 0 -12px
}
.course-item{
align-items: center;
background: white;
padding: 30rpx 12px;
border-bottom: 1rpx solid #EEE;
position: relative;
}
.course-item:after {
content: '进入>';
display: block;
position: absolute;
right: 2rpx;
top: 50%;
height: 40rpx;
line-height: 40rpx;
margin-top: -20rpx;
margin-right: 20rpx;
color: #999;
}
.course-name{
vertical-align: middle;
margin-right: 80rpx;
}
.none-content{
align-self: center;
}
text.none-content{
font-size: 16px;
margin-top: 32rpx;
}
image.none-content{
margin-top: 120rpx;
height: 160rpx;
width: 180rpx;
}

@ -1,5 +1,5 @@
<!--pages/createclass/createclass.wxml-->
<view class="container">
<view hidden="{{true}}" class="container">
<text>创建我的课程</text>
<view class="flex-wrap input-wrap">
<text class="label">课程名称:</text>

@ -0,0 +1,92 @@
// pages/login/login.js
const app = getApp();
Page({
/**
* 页面的初始数据
*/
data: {
error: "",
login: "",
password: ""
},
update_login:function({detail: {value}}){
this.setData({login: value});
},
update_password: function({detail: {value}}){
this.setData({password: value});
},
login: function({currentTarget:{dataset}}){
const {login, password} = this.data;
app.client.login({login: login, password: password, autologin: 1,
success(res){
wx.navigateBack({
delta: 1
})
console.log("login_successful!!!!");
},
fail(error){
wx.showToast({
title: error.toString(),
icon: "none"
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,4 @@
{
"navigationBarTitleText": "登陆educoder",
"usingComponents": {}
}

@ -0,0 +1,24 @@
<view class="container">
<view class="logo-view">
<image class="logo" src="../../images/educoder.png" mode="aspectFit"></image>
</view>
<view class="form-wrap">
<view class="input-wrap">
<input class="login-input"
bindinput="update_login"
placeholder="用户名、邮箱、手机号">
</input>
</view>
<text class="error" wx:if="{{!error}}">{{error}}</text>
<view class="input-wrap">
<input password
class="login-input"
placeholder="密码"
bindinput="update_password">
</input>
</view>
</view>
<button class="login-submit" type="primary" bindtap="login">
登陆
</button>
</view>

@ -0,0 +1,34 @@
.logo-view{
display: flex;
flex-direction: column;
}
.logo{
align-self: center;
width: 160rpx;
height: 160rpx;
margin-top: 40rpx;
}
.input-wrap {
background: #fff;
border-bottom: 1px solid #eee;
margin: 0 -12px;
padding: 0 12px;
height: 46px;
line-height: 46px;
}
.label {
color: #999;
width: 4.5em;
}
.login-input {
font-size: 18px;
line-height: 100%;
height: 100%;
width: 100%;
}
.login-submit{
margin: 24rpx 36rpx;
}
textarea {
width: 100%;
}

@ -92,16 +92,17 @@ Page({
query.include("class");
return query.find().then((presences) => {
this.presences = presences;
classes = presences.map((presence) => {return presence.get("class")});
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}));
})
console.log(classes);
})
}).catch(console.error);
},
/**
* 生命周期函数--监听页面显示

@ -7,7 +7,7 @@ classes: 课程列表 type: Array
-->
<view class="container">
<view class="class-list">
<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">

@ -1,5 +1,5 @@
.class-list {
.course-list {
display: flex;
flex-direction: column;
margin: 0 -12px
@ -57,3 +57,6 @@ image.none-content{
width: 220rpx;
}
.add-class:hover{
opacity: 0.6;
}

@ -1,20 +1,86 @@
const AV = require("../../lib/av-live-query-weapp-min")
const AV = require("../../lib/av-live-query-weapp-min");
const app = getApp();
Page({
data:{
current_user: null
current_user: null,
avatar_url: '',
show_join_course_modal: false,
invite_code: ""
},
enter_usersetting: function(event){
wx.navigateTo({
url: '../user/user'
logout: function(){
app.client.logout({
success:res=>{
console.log("注销成功");
console.log(res);
this.enter_login();
},
fail:error=>{
console.error("注销失败");
console.error(error);
}
})
},
enter_changeuser: function(event){
console.log(event);
enter_login: function(event){
wx.navigateTo({
url: '../changeuser/changeuser'
url: '../login/login',
})
},
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});
},
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;
}
console.log(data);
console.log({ ...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
});
this.cancel_join_course_modal();
})
.catch(error=>{
wx.showToast({
title: error.toString(),
icon: "none"
});
console.warn(error);
})
},
onShow: function(){
this.setData({current_user: AV.User.current().toJSON()})
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})
}
}
// enter_usersetting: function(event){
// wx.navigateTo({
// url: '../user/user'
// })
// },
// enter_changeuser: function(event){
// console.log(event);
// wx.navigateTo({
// url: '../changeuser/changeuser'
// })
// },
})

@ -1,13 +1,26 @@
<view class="setting">
<view class="user-view bg_user">
<open-data type="userAvatarUrl" class="avatar" default-avatar="../../images/avatar.png"></open-data>
<text class="user-text" bindtap="enter_usersetting">{{current_user.name}} | {{current_user.username}}</text>
<!--open-data type="userAvatarUrl" class="avatar" default-avatar="../../images/avatar.png"></open-data-->
<image class="avatar" src="{{avatar_url?avatar_url:'../../images/avatar.png'}}"></image>
<text class="user-text" bindtap="enter_usersetting">{{current_user.real_name}} | {{current_user.username}}</text>
</view>
<view class="nav-list">
<navigator url="../user/user" class="nav user" bindlongpress="enter_changeuser">登陆信息修改</navigator>
<navigator hidden="{{true}}" url="../changeuser/changeuser" class="nav user">更换登陆用户</navigator>
<navigator url="../addclass/addclass" class="nav addclass">加入课程</navigator>
<!--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 url="../about/about" class="nav about">关于</navigator>
</view>
<button class="login" type="primary" wx:if="{{current_user.user_id==2}}" bindtap="enter_login">登陆</button>
<button class="logout" wx:else bindtap="logout">退出登陆</button>
</view>
<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>

@ -31,3 +31,22 @@
height: 341rpx;
margin-bottom: 6rpx;
}
.login{
margin: 16rpx 70rpx;
}
.logout{
background: red;
border-radius: 26rpx;
color: white;
margin: 16rpx 70rpx;
}
.code-input{
border-radius: 10rpx;
border: 1rpx solid;
height: 36px;
margin-bottom: 24rpx;
}
lable.identity{
margin-right: 16rpx;
}

@ -1,4 +1,5 @@
const { User } = require('../../lib/av-live-query-weapp-min');
const app = getApp();
Page({
data: {
@ -8,11 +9,11 @@ Page({
error: null,
},
onLoad: function() {
const user = User.current();
const user = app.client.current_user;
if (user) {
this.setData({
name: user.get("name"),
username: user.get('username'),
name: user.name,
username: user.login,
});
}
},

@ -5,7 +5,7 @@
},
"setting": {
"urlCheck": true,
"es6": false,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true,

Loading…
Cancel
Save