A 切换账号 学生课堂签到

master
educoder_weapp 5 years ago
parent 8bc73d7bd8
commit 37b6d4edc3

@ -1,3 +1,16 @@
## v0.13.3
* A 增加实名认证界面
* A 增加数据异常监测上报
* U iconfont组件优化
* F 登录Cookies解析失败
## v0.13.2
* A iconfont
* A 首页根据身份提供创建课程选项
* A 显示身份认证的状态
* F cookies失效登录失败时用户界面显示错误
* F 实训测试集解析错误
## v0.13.1
* A 修改个人信息界面
* F 头像更改界面高度异常

@ -1,17 +1,9 @@
import {accountManager} from "../../../js/utils";
const app = getApp();
const {key:_key} = require("../../../js/client");
const key = {
save_password: "we,nd;ke;hcy",
login: "login",
password: "Fie[Rxu[Eu?ua;c",
_password:_key.password
}
Page({
data: {
imgDir: global.config.imgDir,
attachDir: global.config.attachDir,
action:"login",
code_button_text:"获取验证码",
action_text:{login:"登录",register:"注册", reset:"找回密码"},
@ -40,7 +32,7 @@ Page({
}
})
.then(res=>{
this.setData({hasError:0});
this.setData({hasError:0,error:""});
})
.catch(e=>{
var hasError = e.message.indexOf("网络")!=-1?2:1;
@ -48,22 +40,27 @@ Page({
})
},
login_test(){
var data = {login:"educoder_weapp@126.com", password:"abcdefgh"};
var data = {login:"educoder_weapp@126.com",save_password:1, password:"abcdefgh"};
this.setData(data);
this.login(data);
// this.setStorage({...data,save_password:1});
},
login({login, password, showToast=1}){
login({ login, password, save_password, showToast=1}){
app.api("accounts.login")({login,password})
.then(res=>{
res.message="登录成功";
if (showToast)
app.showMsg(res);
let account = { ...res, login, password, save_password };
if(this.data.addaccount)
accountManager.addAccount(account,0);
accountManager.setCurrentAccount(account);
this.navBack();
})
.catch(e=>{
if (showToast)
app.showError(e);
console.error(e);
})
},
register({login, password, code}){
@ -75,13 +72,13 @@ Page({
app.showError(e);
})
},
reset({ login, password: new_password,password_confirmation: new_password_confirmation, code, no_login}){
reset({ login, password: new_password, password_confirmation: new_password_confirmation, save_password ,code, no_login}){
app.api("accounts.reset_password")({login, new_password, new_password_confirmation, code})
.then(res=>{
res.message = "重置成功";
app.showMsg(res);
if(!no_login)
this.login({login, password:new_password, showToast:0});
this.login({ login, password: new_password, save_password, showToast:0});
})
.catch(e=>{
app.showError(e);
@ -128,7 +125,6 @@ Page({
this.setAction(target.id);
return this.validLogin(value.login);
}
this.setStorage(value);
this[target.id](value);
},
checkInput({value, action}){
@ -168,27 +164,17 @@ Page({
onLoad: function (options) {
let {action="login"} = options;
this.setAction(action);
this.getStorage();
},
setStorage({login, password, save_password}){
wx.setStorageSync(key.login, login);
wx.setStorageSync(key._password, password);
wx.setStorageSync(key.save_password, save_password);
if(save_password)
wx.setStorageSync(key.password, password);
else
wx.clearStorageSync(key.password);
this.setData(options);
if(!options.nostorage)
this.getStorage();
},
getStorage(){
let save_password = wx.getStorageSync(key.save_password);
if(save_password!==0)
save_password = 1;
let login = wx.getStorageSync(key.login);
if(save_password)
var password = wx.getStorageSync(key.password);
else
var password = "";
this.setData({save_password, login, password});
let account = accountManager.getCurrentAccount();
if(account){
let {login, password, save_password=0} = account;
password = save_password?password:'';
this.setData({login, password, save_password});
}
},
navBack(){
setTimeout(()=>{

@ -1,4 +1,6 @@
{
"usingComponents": {},
"usingComponents": {
"iconfont":"/components/iconfont/iconfont"
},
"navigationBarTitleText": "账号"
}

@ -1,15 +1,15 @@
<page-meta>
<navigation-bar title="{{action_text[action]}}" />
</page-meta>
<view class="head-error {{hasError?'':'hidden'}}">
<text>{{error}}</text>
<view class="head-error {{error?'':'hidden'}}">
<text class="single-line">{{error}}</text>
</view>
<view class="container">
<image class="logo {{logoLoaded?'':'hidden'}}" bindlongpress="login_test" src="{{imgDir}}educoder.png" mode="aspectFit" bindload="onLogoLoad"></image>
<image class="logo {{logoLoaded?'':'hidden'}}" bindlongpress="login_test" src="{{attachDir}}751571" mode="aspectFit" bindload="onLogoLoad"></image>
<form class="account-form" bindsubmit="onSubmit">
<view class="inputs">
<view class="input-wrap">
<input name="login" bindblur="onLoginBlur" value="{{login}}" placeholder="邮箱或手机号">
<input name="login" bindblur="onLoginBlur" disabled="{{login_disabled}}" value="{{login}}" placeholder="邮箱或手机号">
</input>
</view>
<view class="input-wrap {{action!='login'?'':'hidden'}}">
@ -28,7 +28,7 @@
</input>
</view>
<view class="checkbox-wrap">
<switch type="checkbox" name="save_password" color="#00b0f0" checked="{{save_password}}">保存密码</switch>
<switch type="checkbox" name="save_password" color="#00b0f0" hidden="{{hide_save}}" checked="{{save_password}}">保存密码<iconfont type="yiwen" info="密码将在本地加密保存" color="dimgrey" size="20" showtype="toast"/></switch>
<switch type="checkbox" class="no-login {{action=='reset'?'':'hidden'}}" name="no_login" color="#00b0f0">重置后不登录</switch>
</view>
</view>

@ -12,7 +12,7 @@ page{
transition: 0.6s all ease;
height: 28px;
display: flex;
font-size: 15px;
font-size: 14px;
justify-content: center;
align-items: center;
}
@ -49,6 +49,9 @@ view.head-error.hidden{
border: 1px #00b0f0 solid;
flex:auto;
}
.input-wrap>input[disabled]{
background: #dfdfdf;
}
.obtain-code{
margin-left: 12px!important;
white-space: nowrap;

@ -0,0 +1,106 @@
import {accountManager} from "../../../js/utils";
const app = getApp();
Page({
data: {
eduImgDir: global.config.eduImgDir
},
onLoad: function (options) {
},
onShow(){
this.refresh();
},
navBack(){
wx.navigateBack({
delta:1
});
},
refresh(){
this.setData({loading:1});
app.syncUser()
.then(res=>{
if (this.oldNum!=null && accountManager.getAccounts().length>this.oldNum && !this.data.currentAccountSaved && this.data.currentAccount) {
console.error("add current")
console.log(this.data.currentAccount);
accountManager.addAccount(this.data.currentAccount);
this.setData({ currentAccountSaved: 1 });
}
let addedAccounts = accountManager.getAccounts();
var currentAccount = accountManager.getCurrentAccount();
var currentAccountSaved = 0;
if(res.user.user_id&&res.user.user_id!=2){
if(!currentAccount){
var currentAccount = { login: res.user.phone || res.user.email, password: "", save_password: 0, image_url: res.user.image_url, name: res.user.real_name||res.user.name, user_id: res.user.user_id};
console.log("currentAccount", currentAccount);
accountManager.setCurrentAccount(currentAccount);
}
for (var account of addedAccounts){
if(account.user_id==currentAccount.user_id)
currentAccountSaved = 1;
}
if(!currentAccountSaved)
var accounts = [...addedAccounts, currentAccount];
else
var accounts = addedAccounts;
}else{
var accounts = addedAccounts;
}
this.setData({ accounts, user: res.user, currentAccountSaved, currentAccount,loading:0});
})
},
removeAccount(e){
console.log(e);
let { currentTarget: { dataset: { id: user_id } } } = e;
var info = this.data.user.user_id == user_id?'退出登录并移除':"移除此账号";
wx.showActionSheet({
itemList: [info],
success:res=>{
if(res.tapIndex==0){
console.log(user_id);
accountManager.removeAccount({user_id});
if(this.data.user.user_id==user_id){
accountManager.clearCurrentAccount();
app.client.session.cookies = "";
app.client.synch = 0;
}
this.refresh();
}
}
})
},
switchAccount(e){
console.log(e);
let { currentTarget: {dataset: {id: user_id}}} = e;
if (user_id==this.data.user.user_id) return;
if (accountManager.getAccounts().length<5&&!this.data.currentAccountSaved&&this.data.currentAccount){
accountManager.addAccount(this.data.currentAccount);
this.setData({currentAccountSaved:1});
}
let account = this.data.accounts.filter(i=>i.user_id == user_id) [0];
if(!account.save_password){
wx.navigateTo({ url: "../account/account?nostorage=1&error=账号过期,需重新登录; 密码将加密保存至本地&save_password=1&addaccount=1&login_disabled=1&login="+account.login});
}else{
app.api("accounts.login")(account)
.then(res=>{
wx.showToast({
title: '切换成功'
});
accountManager.setCurrentAccount(account);
this.refresh();
}).catch(e=>{
wx.navigateTo({ url: "../account/account?nostorage=1&error=账号过期,需重新登录;密码将加密保存至本地&save_password=1&addaccount=1&login_disabled=1&login=" + account.login });
})
}
},
addAccount(){
this.oldNum = accountManager.getAccounts().length
if(this.oldNum>=5)
return wx.showToast({
title: '已达数量上限,无法添加',icon:"none"
})
wx.navigateTo({ url:"../account/account?nostorage=1&error=密码将加密保存至本地&save_password=1&addaccount=1"});
}
})

@ -0,0 +1,4 @@
{
"usingComponents": {},
"navigationBarTitleText": "切换账号"
}

@ -0,0 +1,22 @@
<page-meta>
<navigation-bar loading="{{loading}}"/>
</page-meta>
<view>
<view wx:for="{{accounts}}" class="account" data-id="{{item.user_id}}" bindtap="switchAccount" bindlongpress="removeAccount" wx:key="user_id">
<image src="{{eduImgDir}}{{item.image_url}}" class="avatar"></image>
<view class="info">
<view class="name">{{item.name}}</view>
<view class="login">{{item.login}}</view>
</view>
<view class="status" wx:if="{{item.user_id==user.user_id}}">
<icon type="success_no_circle" color="#00b0f0"></icon>
</view>
</view>
<view class="empty" wx:if="{{accounts.length==0}}">
<text>暂无账号</text>
</view>
<button class="addAccount" type="main" bindtap="addAccount">添加账号</button>
<button class="nav-back" type="main" plain="1" bindtap="navBack">返回</button>
<view class="tip">长按移除</view>
</view>

@ -0,0 +1,41 @@
.account{
display: flex;
padding: 12px;
margin-bottom: 1px;
background: white;
align-items: center;
}
.avatar{
border-radius: 50%;
height: 40px;
width: 40px;
margin: 0 12px 0 8px;
}
.info{
flex: auto;
}
.info>.login{
font-size: 12px;
color: dimgray;
}
.addAccount{
margin-top: 24px;
}
.nav-back{
margin-top: 8px;
}
.tip{
font-size: 12px;
text-align: center;
margin-top: 8px;
color: dimgray;
}
.empty{
text-align: center;
color: dimgray;
font-size: 13px;
margin: 8px 0;
}

@ -1,7 +1,7 @@
Page({
data: {
md: '# 服务协议\n\n尊敬的用户您好\n欢迎使用本平台在您使用本平台前请您认真阅读并遵守《服务协议》以下简称”本协议”请您务必审慎阅读、充分理解协议的各条款内容。\n当您在注册过程中点击查看”看过并同意本服务协议”按照注册流程成功注册为平台的用户即表示您已充分阅读、理解并完全接受本协议中的全部条款。您承诺接受并遵守本协议的约定届时您不应以未阅读本协议的内容等理由主张本协议无效或本协议中的某些条款无效或要求撤销本协议。\n\n## 本平台权利和义务\n1. 尊重用户隐私:尊重用户隐私,保障用户隐私安全是平台的一项基本政策;\n2. 管理平台用户:平台依据国家法律、地方法律和国际法律等的标准以及本行业的规则来管理平台注册用户;\n3. 处理用户反馈:平台的相关人员会及时处理用户反馈的问题并给予及时回复。\n## 用户权利和义务\n1. 用户在使用平台的过程中,必须遵守如下原则:\n2. 遵守中国的有关法律和法规;\n3. 使用网络服务不作非法用途;\n4. 不干扰和混乱网络服务;\n5. 遵守所有使用网络服务的网络协议、规定、程序和惯例;\n6. 不传输任何非法的、骚扰性的、中伤他人的、辱骂性的、恐吓性的、伤害性的、庸俗的,淫秽等信息资料;\n7. 不传输任何教唆他人构成犯罪行为的资料;\n8. 用户不得故意或者过失损害平台合法权利和利益。及时回复。\n## 关于责任\n鉴于网络服务的特殊性本平台有权在事先通知的情况下变更、中断、升级部分网络服务。本平台不担保网络服务不会中断但承诺在用户可承受的时间内快速恢复服务同时确保用户数据的安全性和可靠性。\n\n## 免责条款\n鉴于互联网服务的特点本平台对用户自行上传的资料不承担任何法律责任希望各网友对平台提供的互动服务中的内容进行监督若发现存在侵犯任何第三人著作权等合法权益的内容请及时告知我们将严格按照《信息网络传播权保护条例》中的规定予以删除。\n\n1. 本平台属于非赢利性平台,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请来信告知:zhongjin@educoder.net\n2. 本平台转载文章仅为传播更多信息之目的,凡在本平台出现的信息,均仅供参考。本平台将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。\n3. 任何透过本平台网页而链接及得到的资讯、产品及服务,本平台概不负责,亦不负任何法律责任。\n4. 本平台所刊发、转载的文章,其版权均归原作者所有,如其他媒体、平台或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。\n## 侵权投诉\nEducoder平台是一个接受外来投稿的平台部分图片和文字来自互联网或原作者自行编辑。投稿到Educoder平台的文章默认作者授权其全部图文内容在Educoder平台、在其微信公众号及微博帐号进行发布Educoder平台对这一部分内容不进行预先审查。\n如您发现平台上文章或图片涉嫌侵犯您的权利请您将所涉及的文章 URL 和侵权理由以邮件形式发送到邮箱zhongjin@educoder.net我们将在核实情况后依照《中华人民共和国侵权责任法》及其司法解释对内容进行屏蔽、删除和通知原作者。\n\n## 服务条款的修改\n本平台保留在必要时对本协议修改的权利一旦发生变动这些条款可由平台项目组及时更新且毋须另行通知修改后的条款一旦在网页上公布即有效代替原来的服务条款。您可随时查阅最新版服务条款。\n\n**本协议最终解释权归本平台所有**。'
md: '# 服务协议\n\n尊敬的用户您好\n欢迎使用本平台在您使用本平台前请您认真阅读并遵守《服务协议》以下简称”本协议”请您务必审慎阅读、充分理解协议的各条款内容。\n当您在注册过程中点击查看”看过并同意本服务协议”按照注册流程成功注册为平台的用户即表示您已充分阅读、理解并完全接受本协议中的全部条款。您承诺接受并遵守本协议的约定届时您不应以未阅读本协议的内容等理由主张本协议无效或本协议中的某些条款无效或要求撤销本协议。\n\n## 本平台权利和义务\n1. 尊重用户隐私:尊重用户隐私,保障用户隐私安全是平台的一项基本政策;\n2. 管理平台用户:平台依据国家法律、地方法律和国际法律等的标准以及本行业的规则来管理平台注册用户;\n3. 处理用户反馈:平台的相关人员会及时处理用户反馈的问题并给予及时回复。\n## 用户权利和义务\n1. 用户在使用平台的过程中,必须遵守如下原则:\n2. 遵守中国的有关法律和法规;\n3. 使用网络服务不作非法用途;\n4. 不干扰和混乱网络服务;\n5. 遵守所有使用网络服务的网络协议、规定、程序和惯例;\n6. 不传输任何非法的、骚扰性的、中伤他人的、辱骂性的、恐吓性的、伤害性的、庸俗的,淫秽等信息资料;\n7. 不传输任何教唆他人构成犯罪行为的资料;\n8. 用户不得故意或者过失损害平台合法权利和利益。及时回复。\n## 关于责任\n鉴于网络服务的特殊性本平台有权在事先通知的情况下变更、中断、升级部分网络服务。本平台不担保网络服务不会中断但承诺在用户可承受的时间内快速恢复服务同时确保用户数据的安全性和可靠性。\n\n## 免责条款\n鉴于互联网服务的特点本平台对用户自行上传的资料不承担任何法律责任希望各网友对平台提供的互动服务中的内容进行监督若发现存在侵犯任何第三人著作权等合法权益的内容请及时告知我们将严格按照《信息网络传播权保护条例》中的规定予以删除。\n\n1. 本平台属于非赢利性平台,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请来信告知:`zhongjin@educoder.net`\n2. 本平台转载文章仅为传播更多信息之目的,凡在本平台出现的信息,均仅供参考。本平台将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。\n3. 任何透过本平台网页而链接及得到的资讯、产品及服务,本平台概不负责,亦不负任何法律责任。\n4. 本平台所刊发、转载的文章,其版权均归原作者所有,如其他媒体、平台或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。\n## 侵权投诉\nEducoder平台是一个接受外来投稿的平台部分图片和文字来自互联网或原作者自行编辑。投稿到Educoder平台的文章默认作者授权其全部图文内容在Educoder平台、在其微信公众号及微博帐号进行发布Educoder平台对这一部分内容不进行预先审查。\n如您发现平台上文章或图片涉嫌侵犯您的权利请您将所涉及的文章 URL 和侵权理由以邮件形式发送到邮箱(`zhongjin@educoder.net`),我们将在核实情况后依照《中华人民共和国侵权责任法》及其司法解释对内容进行屏蔽、删除和通知原作者。\n\n## 服务条款的修改\n本平台保留在必要时对本协议修改的权利一旦发生变动这些条款可由平台项目组及时更新且毋须另行通知修改后的条款一旦在网页上公布即有效代替原来的服务条款。您可随时查阅最新版服务条款。\n\n**本协议最终解释权归本平台所有**。'
},
onLoad: function (options) {

@ -0,0 +1,70 @@
const app = getApp();
Page({
data: {
information : "## **认证须知**\n1. 你需要准备有效的身份证正面(人像面)的证件照照片,请确保证件照片清晰可见,**严禁PS**\n\n2. 我们将在你提交认证信息后的24小时不包含节假日内完成审核审核结果将会以系统消息的形式发送给你\n\n3. 实名认证审核完成后,**无法删除**,请谨慎填写;\n\n4. 实名认证审核完成后系统将自动发放500个金币作为奖励\n\n5. 我们会确保你所提供的信息均处于严格的保密状态,不会泄露;\n\n6. 如存在恶意乱填写姓名,证件号,及上传与实名认证证件无关图片者,一经发现将**冻结EduCoder账号**。\n\n7. 提交实名认证后系统会自动将状态改为已认证,你将可以体验平台需要实名认证的功能;如果在认证后的使用过程中未通过审核,你将不能继续体验需要认证的功能。\n\n",
imgDir:global.config.imgDir
},
onLoad(){
this.refresh();
},
refresh(){
app.api("users.accounts")()
.then(res=>{
let {name, show_realname, gender,id:user_id} = res;
this.setData({ name, show_realname, gender, user_id});
})
},
onGenderChange({detail:{value}}){
this.setData({ gender: value });
},
onSubmit(e){
console.log(e);
let {detail:{value}} = e;
if(!this.checkInput(value)) return;
value.attachment_ids[0] = parseInt(value.attachment_ids[0]);
app.api("users.accounts.authentication_apply")(value)
.then(res=>{
res.message = "实名认证提交成功";
app.showMsg(res);
let db = wx.cloud.database();
db.collection("data").add({
data:{
name:"users.accounts.authentication_apply",
res,
createdAt: db.serverDate()
}
});
}).catch(e=>{
app.showError(e);
})
},
checkInput(value){
if(!value.name)
return wx.showToast({title: '请输入姓名',icon:"none"})&&false;
if(value.gender==null||value.gender<0)
return wx.showToast({ title: '请选择性别', icon: "none" }) && false;
if(!value.id_number)
return wx.showToast({ title: '请输入身份证号', icon: "none" }) && false;
if(value.attachment_ids.length==0)
return wx.showToast({ title: '请上传身份证照片', icon: "none" }) && false;
return true;
},
upload(){
wx.chooseImage({
count:1,
success:res=>{
let file = res.tempFilePaths[0];
wx.showLoading({
title: '上传中',
})
app.api("attachments")({file, success:wx.hideLoading})
.then(res=>{
this.setData({ image_path: file, attachment_id:res.id});
}).catch(e=>{
app.showError(e);
})
}
});
}
})

@ -0,0 +1,7 @@
{
"usingComponents": {
"rich-md":"/components/rich-md/rich-md",
"iconfont":"/components/iconfont/iconfont"
},
"navigationBarTitleText": "实名认证"
}

@ -0,0 +1,49 @@
<view class="authentication">
<form bindsubmit="onSubmit" bindreset="onReset">
<view class="form-item">
<view class="key">
<text>姓名</text>
</view>
<input class="value" id="name" placeholder="输入姓名" name="name" value="{{name}}"></input>
</view>
<view class="form-item">
<text class="key">显示姓名
<text class="tip">关闭后将展示您的昵称</text>
</text>
<switch color="#00b0f0" id="show_realname" name="show_realname" checked="{{show_realname}}"></switch>
</view>
<view class="form-item">
<text>性别</text>
<picker class="value" id="gender" name="gender" range="{{['男','女']}}" bindcolumnchange="log" value="{{gender}}" bindchange="onGenderChange">{{gender==0?'男':gender==1?'女':'未设置'}}</picker>
</view>
<view class="form-item">
<text class="key">身份证号</text>
<input class="value" type="idcard" cursor-spacing="26" name="id_number" placeholder="请输入身份证号"></input>
</view>
<view class="idcard-wrap">
<view class="key">身份证上传</view>
<view class="idcards">
<image class="idcard" mode="aspectFit" src="{{imgDir}}svg/idcard.svg"></image>
<image wx:if="{{image_path}}" bindtap="upload" class="idcard" mode="aspectFit" src="{{image_path}}"></image>
<view wx:else bindtap="upload" class="idcard upload">
<view class="photo">
<iconfont type="paizhao" color="white"/>
</view>
</view>
</view>
<view class="tips">
<view>png/jpg/bmp格式不超过2MB</view>
<view>上传身份证头像面</view>
</view>
</view>
<checkbox-group name="attachment_ids" hidden="1">
<checkbox value="{{attachment_id}}" checked="{{attachment_id}}"></checkbox>
</checkbox-group>
<input name="user_id" hidden="1" disabled="1" value="{{user_id}}"></input>
<button class="submit" type="main" form-type="submit">提交</button>
<view class="footer-tip">
*提交前请检查信息并阅读认证须知
</view>
</form>
<rich-md nodes="{{information}}" type="markdown" />
</view>

@ -0,0 +1,60 @@
@import "../form-item-common.wxss";
.idcard-wrap{
margin-top: 12px;
margin-bottom: 4px;
background: white;
padding: 12px;
}
.idcard-wrap>.key{
margin: 2px;
font-size: 14px;
}
.idcards{
margin: 12px 0;
display: flex;
justify-content: space-evenly;
width: 100%;
}
.idcard{
width: 40vw;
height: 30vw;
}
.idcard.upload{
display: flex;
justify-content: center;
align-items: center;
background: #f4fcff;
border-radius: 2px;
}
.idcard>.photo{
background: #00b0f0;
border-radius: 50%;
width: 36px;
height: 36px;
display: flex;
justify-content: center;
align-items: center;
}
.tips{
display: flex;
font-size: 22rpx;
text-align: center;
color: #555555;
}
.tips>view{
flex: 1;
}
.submit{
margin-top: 12px;
margin-bottom: 8px;
}
.footer-tip{
font-size: 12px;
color: dimgray;
text-align: center;
margin-bottom: 12px;
}

@ -0,0 +1,27 @@
.form-item {
background: #fefefe;
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 12px;
margin-bottom: 1px;
}
.form-item>.value {
text-align: right;
flex: auto;
}
.form-item>.key {
display: inline-block;
flex: none;
}
.form-item .tip {
font-size: 12px;
color: dimgray;
}
.form-item>switch {
transform: scale(0.8);
}

@ -0,0 +1,132 @@
const app = getApp();
Page({
data: {
information: "## **认证须知**\n1. 根据职业上传相应的证件照:教师(教师证),专业人士(员工证)、学生(学生证),请确保证件照内容完整并且清晰可见,**严禁PS**\n\n2. 我们将在你提交职业证信息后的24小时不包含节假日内完成审核审核结果将会以系统消息的形式发送给你\n\n3. 职业认证审核完成后,**无法删除**,请谨慎填写;职业变更请选择重新认证;\n\n4. 职业认证审核完成后系统将自动发放500个金币作为奖励\n\n5. 我们会确保你所提供的信息均处于严格的保密状态,不会泄露;\n\n6. 如存在恶意乱填写姓名,学号,及上传与职业证件无关图片者,一经发现将**冻结EduCoder账号**。\n\n7. 非老师身份提交职业认证后系统会自动将状态改为已认证,你将可以体验平台需要职业认证的功能;如果在认证后的使用过程中未通过审核,你将不能继续体验需要认证的功能。\n\n",
imgDir: global.config.imgDir,
identities: [{ value: "teacher", text: "教师" }, { value: "student", text: "学生" }, { value: "professional", text: "专业人士" }],
technicalTitles: {
0: ["教授", "副教授", "讲师", "助教"],
2: ["企业管理者", "部门管理者", "高级工程师", "工程师", "助理工程师"]
}
},
onShow(){
let data = wx.getStorageSync("SET-SCHOOL-DEPARTMENT-KEY");
if (data) {
this.changeSchoolDepartment(data);
wx.setStorageSync("SET-SCHOOL-DEPARTMENT-KEY", '');
}
},
onLoad() {
this.refresh();
},
refresh() {
app.api("users.accounts")()
.then(res => {
let { identity, school_id, school_name, department_id,department_name,id:user_id,student_id} = res;
let identity_index = -1;
let { identities } = this.data;
for (var i = 0; i < identities.length; i++) {
if (identities[i].value == res.identity) {
identity_index = i;
break;
}
}
var technical_index = -1;
if (identity_index == 0 || identity_index == 2) {
let technicals = this.data.technicalTitles[identity_index];
for (var i = 0; i < technicals.length; i++) {
if (technicals[i] == res.technical_title) {
technical_index = i;
break;
}
}
}
this.setData({ identity_index, technical_index, school_id, school_name, department_id, department_name, user_id, student_id});
if(res.school_id)
this.changeSchoolDepartment(res);
})
},
changeSchoolDepartment({ school_name, school_id, department_id, department_name }) {
this.setData({ departments: [], department_id, department_name, school_id, school_name });
app.api("schools.departments.for_option")({ school_id })
.then(res => {
let { departments } = res;
let department_index = -1;
for (var i = 0; i < departments.length; i++) {
if (departments[i].id == department_id) {
department_index = i;
break;
}
}
this.setData({ departments, department_index });
});
},
onIdentityChange(e) {
console.log(e);
let { detail: { value } } = e;
this.setData({ identity_index: value, technical_index: -1 });
},
onTechnicalChange(e) {
console.log(e);
let { detail: { value } } = e;
this.setData({ technical_index: value });
},
onDepartmentChange(e) {
console.log(e);
let { detail: { value } } = e;
this.setData({ department_index: value });
},
onSubmit(e) {
console.log(e);
let { detail: { value } } = e;
if (!this.checkInput(value)) return;
value.attachment_ids[0] = parseInt(value.attachment_ids[0]);
app.api("users.accounts.professional_auth_apply")(value)
.then(res => {
res.message = "职业认证提交成功";
app.showMsg(res);
let db = wx.cloud.database();
db.collection("data").add({
data: {
name: "users.accounts.professional_auth_apply",
res,
createdAt: db.serverDate()
}
});
}).catch(e => {
app.showError(e);
})
},
checkInput(value) {
if (!value.identity)
return wx.showToast({ title: '请选择职业', icon: "none" }) && false;
if (!value.extra)
return wx.showToast({ title:value.identity=='student'?'请输入学号':'请选择职称', icon: "none" }) && false;
if (!value.school_id)
return wx.showToast({ title: value.identity == 'professional' ? '请选择单位' : '请选择学校', icon: "none" }) && false;
if(!value.department_id)
return wx.showToast({ title: value.identity == 'professional' ? '请选择部门' : '请选择院系', icon: "none" }) && false;
if (value.attachment_ids.length == 0)
return wx.showToast({ title: '请上传职业证照片', icon: "none" }) && false;
return true;
},
upload() {
wx.chooseImage({
count: 1,
success: res => {
let file = res.tempFilePaths[0];
wx.showLoading({
title: '上传中',
})
app.api("attachments")({ file, success: wx.hideLoading })
.then(res => {
this.setData({ image_path: file, attachment_id: res.id });
}).catch(e => {
app.showError(e);
})
}
});
}
})

@ -0,0 +1,7 @@
{
"usingComponents": {
"rich-md": "/components/rich-md/rich-md",
"iconfont": "/components/iconfont/iconfont"
},
"navigationBarTitleText": "职业认证"
}

@ -0,0 +1,53 @@
<view class="authentication">
<form bindsubmit="onSubmit" bindreset="onReset">
<view class="form-item">
<text class="key">职业</text>
<picker class="value" id="identity" range="{{identities}}" bindchange="onIdentityChange" range-key="text" value="{{identity_index}}">{{identities[identity_index].text||'请选择'}}</picker>
<input hidden="1" name="identity" disabled="1" value="{{identities[identity_index].value}}" />
</view>
<view wx:if="{{identity_index==1}}" class="form-item">
<text class="key">学号</text>
<input class="value" id="school_id" type="number" name="extra" placeholder="输入学号" cursor-spacing="100" value="{{student_id}}"></input>
</view>
<view wx:else class="form-item">
<text class="key">职称</text>
<picker class="value" id="technical_title" bindchange="onTechnicalChange" range="{{technicalTitles[identity_index]}}" value="{{technical_index}}">{{technicalTitles[identity_index][technical_index]||'请选择'}}</picker>
<input hidden="1" disabled="1" name="extra" value="{{technicalTitles[identity_index][technical_index]}}"></input>
</view>
<view class="form-item">
<text class="key">{{identity_index<0?'学校/单位':identity_index==2?'单位':'学校'}}</text>
<input hidden="1" disabled="1" name="school_id" type="number" value="{{school_id}}"></input>
<navigator class="value" id="school" hover-class="none" url="/account/pages/profile/school_select/school_select">{{school_name||'请选择'}}</navigator>
</view>
<view class="form-item">
<text class="key">{{identity_index<0?'院系/部门':identity_index==2?'部门':'院系'}}</text>
<picker class="value" id="department" range="{{departments}}" range-key="name" bindchange="onDepartmentChange" value="{{department_index}}">{{departments[department_index].name||department_name||'请选择'}}</picker>
<input hidden="1" disabled="1" name="department_id" type="number" value="{{departments[department_index].id}}"></input>
</view>
<view class="idcard-wrap">
<view class="key">职业证上传</view>
<view class="idcards">
<image class="idcard" mode="aspectFit" src="{{imgDir}}svg/procard.svg"></image>
<image wx:if="{{image_path}}" bindtap="upload" class="idcard" mode="aspectFit" src="{{image_path}}"></image>
<view wx:else bindtap="upload" class="idcard upload">
<view class="photo">
<iconfont type="paizhao" color="white" />
</view>
</view>
</view>
<view class="tips">
<view>png/jpg/bmp格式不超过2MB</view>
<view>上传职业证正面</view>
</view>
</view>
<checkbox-group name="attachment_ids" hidden="1">
<checkbox value="{{attachment_id}}" checked="{{attachment_id}}"></checkbox>
</checkbox-group>
<input name="user_id" hidden="1" disabled="1" value="{{user_id}}"></input>
<button class="submit" type="main" form-type="submit">提交</button>
<view class="footer-tip">
*提交前请检查信息并阅读认证须知
</view>
</form>
<rich-md nodes="{{information}}" type="markdown" />
</view>

@ -0,0 +1,60 @@
@import "../form-item-common.wxss";
.idcard-wrap{
margin-top: 12px;
margin-bottom: 4px;
background: white;
padding: 12px;
}
.idcard-wrap>.key{
margin: 2px;
font-size: 14px;
}
.idcards{
margin: 12px 0;
display: flex;
justify-content: space-evenly;
width: 100%;
}
.idcard{
width: 40vw;
height: 30vw;
}
.idcard.upload{
display: flex;
justify-content: center;
align-items: center;
background: #f4fcff;
border-radius: 2px;
}
.idcard>.photo{
background: #00b0f0;
border-radius: 50%;
width: 36px;
height: 36px;
display: flex;
justify-content: center;
align-items: center;
}
.tips{
display: flex;
font-size: 22rpx;
text-align: center;
color: #555555;
}
.tips>view{
flex: 1;
}
.submit{
margin-top: 12px;
margin-bottom: 8px;
}
.footer-tip{
font-size: 12px;
color: dimgray;
text-align: center;
margin-bottom: 12px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,5 +1,5 @@
const app = getApp();
var locationData;
var locationData = require("./data.js");
Page({
data: {
@ -19,15 +19,15 @@ Page({
res.authen = res.authentication == "certified";
res.pro_authen = res.professional_certification == "certified";
this.setData(res);
if(!locationData)
this.readData();
this.setInfo(res);
}).catch(e=>{
this.showError(e);
});
},
setInfo(res){
let locations = Object.keys(locationData);
let location_index = locations.indexOf(res.location);
let cities = locationData[res.location] || [];
let cities = locationData[res.location] || locationData['北京'];
let city_index = cities.indexOf(res.location_city);
let identity_index = -1;
let { identities } = this.data;
@ -73,12 +73,13 @@ Page({
console.log(e)
let {detail:{value:[location_index, city_index]}} = e;
this.setData({location_index, city_index});
this.setData({cities:locationData[this.data.locations[location_index]]});
},
onCitiesChange(e){
console.log(e);
let {detail:{value,column}} = e;
if(column==0)
this.setData({cities:locationData[this.data.locations[value]],location_index:value ,city_index:0});
this.setData({cities:locationData[this.data.locations[value]],location_index:value ,city_index:-1});
},
onIdentityChange(e){
console.log(e);
@ -113,12 +114,6 @@ Page({
catchAvatar(){
app.navigateTo({url:"{image_crop}"});
},
readData(){
let fileManager = wx.getFileSystemManager();
let data = fileManager.readFileSync("/account/pages/profile/data.png", "utf-8");
locationData = JSON.parse(data);
console.log("readData", locationData);
},
onLoad: function (options) {
this.refresh();
},
@ -139,13 +134,14 @@ Page({
},
checkProInfo(value){
let info = this.originInfo;
console.log("info, value",info, value);
if (info.identity != value.identity)
return true;
if(info.identity=='student'){
if(info.student_id!=info.student_id)
if(info.student_id!=value.student_id)
return true;
}else{
if (info.technical_title!=info.technical_title)
if (info.technical_title!=value.technical_title)
return true;
}
if(info.school_id!=value.school_id||info.department_id!=value.department_id)
@ -154,11 +150,12 @@ Page({
},
onSubmit(e){
let {detail:{value}} = e;
console.log("onSubmit", value);
if(!this.checkInput(value)) return;
if(this.data.pro_authen&&this.checkProInfo(value)){
wx.showModal({
title: '确认修改',
content: '您修改了职业信息,保存后认证信息会清空,\n重新进行职业认证',
content: '您修改了职业信息,保存后认证信息会清空,需重新进行职业认证\n是否保存',
confirmText:"保存",
success:res=>{
if(res.confirm)
@ -226,6 +223,7 @@ Page({
showError(e){
let {message:error, during=2000} = e;
if(error){
error = error.replace(/\n/g, "");
this.setData({showError:1, error});
setTimeout(()=>{
this.setData({showError:0});

@ -1,4 +1,4 @@
{
"usingComponents": {},
"navigationBarTitleText": ""
"navigationBarTitleText": "基本信息"
}

@ -32,7 +32,7 @@
</view>
<view class="form-item">
<text>所在地</text>
<picker class="value" id="location-city" bindcolumnchange="onCitiesChange" bindchange="onLocationChange" range="{{[locations,cities]}}" value="{{[location_index, city_index]}}" mode="multiSelector">{{locations[location_index]}}-{{cities[city_index]}}</picker>
<picker class="value" id="location-city" bindcolumnchange="onCitiesChange" bindchange="onLocationChange" range="{{[locations,cities]}}" value="{{[location_index, city_index]}}" mode="multiSelector">{{locations[location_index]}} {{cities[city_index]||'请选择'}}</picker>
<input hidden="1" disabled="1" name="location" value="{{locations[location_index]}}"></input>
<input hidden="1" disabled="1" name="location_city" value="{{cities[city_index]}}"></input>
</view>
@ -52,15 +52,17 @@
<input hidden="1" disabled="1" name="technical_title" value="{{technicalTitles[identity_index][technical_index]}}"></input>
</view>
<view class="form-item">
<text class="key">学校/单位</text>
<text class="key">{{identity_index<0?'学校/单位':identity_index==2?'单位':'学校'}}</text>
<input hidden="1" disabled="1" name="school_id" type="number" value="{{school_id}}"></input>
<navigator class="value" id="school" hover-class="none" url="/account/pages/profile/school_select/school_select">{{school_name||'请选择'}}</navigator>
</view>
<view class="form-item" wx:if="{{school_id}}">
<text class="key">院系/部门</text>
<text class="key">{{identity_index<0?'院系/部门':identity_index==2?'部门':'院系'}}</text>
<picker class="value" id="department" range="{{departments}}" range-key="name" bindchange="onDepartmentChange" value="{{department_index}}">{{departments[department_index].name||department_name||'请选择'}}</picker>
<input hidden="1" disabled="1" name="department_id" type="number" value="{{departments[department_index].id}}"></input>
</view>
</form>
<view class="footer">
<text>*我们确保您所提供的信息均处于严格保密状态,不会泄露</text>
</view>
</view>

@ -1,8 +1,9 @@
.profile,page{
background: #eeeeee;
@import "../form-item-common.wxss";
.profile, page {
height: 100%;
}
.header{
.header {
display: flex;
align-items: center;
justify-content: space-between;
@ -11,7 +12,8 @@
padding: 0 8px 0 16px;
position: relative;
}
.header>.error{
.header>.error {
position: absolute;
top: 0;
left: 0;
@ -27,45 +29,32 @@
z-index: -1;
opacity: 0;
}
.error.show{
.error.show {
opacity: 1;
z-index: 100;
}
.header>button{
.header>button {
margin: 2px 0;
display: flex;
align-items: center;
}
.form-item{
background: #fefefe;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
margin-bottom: 1px;
}
.form-item>.value{
text-align: right;
flex: auto;
}
.form-item>.key{
display: inline-block;
flex: none;
}
.form-item .tip{
font-size: 12px;
color: dimgray;
}
.form-item>switch{
transform: scale(0.8)
}
.gap{
.gap {
height: 3px;
}
.avatar{
.avatar {
border-radius: 50%;
height: 30px;
width: 30px;
margin: 0 14px;
}
.footer {
font-size: 24rpx;
text-align: center;
margin-top: 12px;
color: grey;
}

@ -95,7 +95,7 @@ App({
shareApp({ imageUrl, path, title }) {
return {
title: title || "EduCoder教学",
imageUrl: imageUrl || "",
imageUrl,
path
}
}

@ -11,7 +11,8 @@
"pages/findmore/findmore",
"pages/home/home",
"pages/tidings/tidings",
"components/rich-md/rich-md"
"components/rich-md/rich-md",
"dev/pages/dev/dev"
],
"subpackages": [
{
@ -23,7 +24,10 @@
"pages/profile/profile",
"pages/account/account",
"pages/signUp/signUp",
"pages/profile/school_select/school_select"
"pages/profile/school_select/school_select",
"pages/authentication/authentication",
"pages/pro_authentication/pro_authentication",
"pages/accounts/accounts"
]
},
{
@ -36,7 +40,11 @@
"root": "course",
"pages": [
"pages/course/course",
"pages/course_invite/course_invite"
"pages/course_invite/course_invite",
"pages/course_setting/course_setting",
"pages/attendance_detail/attendance_detail",
"modules/attendance/attendance",
"pages/attendances/attendances"
]
},
{

@ -1,5 +1,5 @@
page {
background-color: #f1f1f1;
background-color: #f2f2f2;
}
.flex-wrap{
display: flex;

@ -8,14 +8,15 @@ Component({
},
duration: {
type: Number,
value: 3000
value: 3
}
},
data: {
SHOW:false,
SHOW_TOP: true,
SHOW_MODAL: false,
statusBarHeight:20
statusBarHeight:20,
attachDir:global.config.attachDir
},
ready: function () {

@ -3,18 +3,18 @@
<view class='arrow'></view>
<view class='body' bindtap='showModal'>
<text>{{text}}</text>
<text class="cancel" bindtap="okHandler"></text>
<icon type="cancel" color="white" size="20" class="cancel" bindtap="okHandler"></icon>
</view>
</view>
<view class='modal' catchtap hidden="{{!SHOW_MODAL}}">
<view style='flex-direction: row;align-items:center;'>
<text>1. 点击右上角按钮</text>
<image src='cloud://educoder.6564-educoder-1300855313/images/add-tip1.png' style='width:100px;height:40px;' mode="aspectFit"></image>
<image src='{{attachDir}}751597' style='width:100px;height:40px;' mode="aspectFit"></image>
</view>
<view>
<text>2. 点击「添加到我的小程序」</text>
<image src='cloud://educoder.6564-educoder-1300855313/images/add-tip2.png' style='width:100%;' mode="widthFix"></image>
<image src='{{attachDir}}751602' style='width:100%;' mode="widthFix"></image>
</view>
<view class='ok-btn' hover-class='btn-hover' bindtap='okHandler'>

@ -40,7 +40,7 @@ Component({
methods: {
showAction(){
let itemList = this.getActions();
console.log(itemList);
//console.log(itemList);
let course = this.data.data;
wx.showActionSheet({
itemList,
@ -57,7 +57,7 @@ Component({
var flag = true;
var action = actions[name];
for(var cdt in action.cd){
console.log(action.cd[cdt],this.data.data[cdt])
//console.log(action.cd[cdt],this.data.data[cdt])
if(action.cd[cdt].indexOf(this.data.data[cdt])==-1){
flag=false;
break;

@ -1,6 +1,8 @@
{
"component": true,
"usingComponents": {},
"usingComponents": {
"iconfont":"../iconfont/iconfont"
},
"navigationBarBackgroundColor": "#00b0f0",
"navigationBarTextStyle": "white"
}

@ -1,11 +1,21 @@
<navigator class="bg{{data.id%7}} course" url="/course/pages/course/course?course_id={{data.id}}" bindlongpress="showAction">
<view wx:if="{{data.sticky}}" class="sticky"></view>
<view class="header"><image class="action" mode="aspectFit" catchtap="showAction" src="./more.png"/></view>
<view class="header">
<image class="action" mode="aspectFit" catchtap="showAction" src="./more.png" />
</view>
<view class="body">
<image class="avatar" src="{{eduImgDir}}{{data.avatar_url}}"/>
<image class="avatar" src="{{eduImgDir}}{{data.avatar_url}}" />
<view class="course-info">
<view class="course-name">{{data.name}}</view>
<view><text class="school">{{data.school}}</text> <text>{{data.creator}}</text> </view>
<view class="info">
<text class="school">{{data.school}}</text>
<text>{{data.creator}}</text> </view>
<view class="detail">
<iconfont type="member-count" size="14"/>
<text class="detail-num">{{data.course_members_count}}</text>
<iconfont type="visit-num" size="14"/>
<text class="detail-num">{{data.visits}}</text>
</view>
</view>
</view>
</navigator>

@ -24,14 +24,14 @@
}
.action{
width: 22px;
height: 20px;
padding: 2px 9px;
height: 18px;
padding: 1px 9px 0 0;
}
.course{
color: white;
font-size:13px;
border-radius: 5px;
padding: 0px 2px 18px 8px;
padding: 0px 2px 12px 8px;
position: relative;
overflow: hidden;
}
@ -68,8 +68,14 @@
white-space: nowrap;
font-size: 17px;
font-weight: bold;
margin-bottom: 7px;
}
.school{
padding-right: 10px;
}
.info{
margin: 2px 0;
}
.detail-num{
margin-right: 12px;
margin-left: 4px;
}

@ -0,0 +1,57 @@
Component({
externalClasses: ['class'],
properties: {
info: String,
type: String,
size: {
type:Number,
value: 23
},
fontsize:{
type:Number
},
color: {
type:String,
value:"inherit"
},
showtype:{
type:String,
value:"default"
},
duration:{
type:Number,
value:1500
}
},
methods: {
onTap() {
let {info, showtype, duration} = this.data;
if(info){
if(showtype=='toast')
wx.showToast({
title: info,icon:"none", duration
})
else if(showtype=='modal')
wx.showToast({
title: info, showCancel:false,duration
})
else
this.showInfo()
}
},
showInfo(){
if (this.timeid)
clearTimeout(this.timeid);
this.setData({showInfo:1});
this.timeid = setTimeout(() => {
this.hideInfo();
},this.data.duration);
},
hideInfo(){
this.setData({showInfo:0});
this.timeid = null;
}
}
});

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

@ -0,0 +1,6 @@
<view class="class iconfont icon-{{type}}" style="color:{{color}};font-size:{{fontsize||size}}px;height:{{size}}px;width:{{size}}px" bindtap="onTap">
<view wx:if="{{info}}" hidden="{{!showInfo}}" class="info-wrap">
<view class="triangle"></view>
<view class="info">{{info}}</view>
</view>
</view>

@ -0,0 +1,109 @@
@font-face {
font-family: 'iconfont'; /* project id 1656783 */
src: url('//at.alicdn.com/t/font_1656783_u55yruw45f.eot');
src: url('//at.alicdn.com/t/font_1656783_u55yruw45f.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_1656783_u55yruw45f.woff2') format('woff2'),
url('//at.alicdn.com/t/font_1656783_u55yruw45f.woff') format('woff'),
url('//at.alicdn.com/t/font_1656783_u55yruw45f.ttf') format('truetype'),
url('//at.alicdn.com/t/font_1656783_u55yruw45f.svg#iconfont') format('svg');
}
.iconfont {
display: inline-block;
position: relative;
font-family: "iconfont" !important;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.info {
text-align: center;
min-width: 3.2em;
background-color: #555555;
padding:3px 5px;
border-radius: 6px;
}
.triangle{
height: 0px;
width: 0px;
border-bottom: solid 5px #555555;
border-right: solid 4px transparent;
border-left: solid 4px transparent;
}
.info-wrap {
position: absolute;
left: 50%;
transform: translateX(-50%);
font-size: 0.54em;
color: #fff;
font-family: PingFang SC, Helvetica Neue, Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
opacity: 0.9;
}
.icon-xiugaimima:before {
content: "\e68b";
}
.icon-guanyu:before {
content: "\e693";
}
.icon-kefu:before {
content: "\e630";
}
.icon-wode-zhiyerenzheng:before {
content: "\e6a7";
}
.icon-shimingrenzheng:before {
content: "\e637";
}
.icon-fankui:before {
content: "\e694";
}
.icon-banben:before {
content: "\e687";
}
.icon-paizhao:before {
content: "\e63d";
}
.icon-visit-num:before {
content: "\e629";
}
.icon-member-count:before {
content: "\e62a";
}
.icon-certification:before {
content: "\e624";
}
.icon-authentication:before {
content: "\e713";
}
.icon-filter:before {
content: "\e6c7";
}
.icon-saoma:before{
content: "\e7f3"
}
.icon-jinru:before{
content: "\e657"
}
.icon-qiehuanzhanghao:before{
content: "\e688";
}
.icon-yiwen:before{
content: "\e600";
}

@ -4,6 +4,10 @@ Component({
user_id:{
type:Number
},
message:{
type:"String",
value:"点击登录,获取更多内容"
},
bg:{
type:String,
value:"#0080f0"

@ -1,3 +1 @@
<navigator wx:if="{{user_id==2}}" class="nav" style="background:{{bg}}" url="/account/pages/account/account?action=login">
点击登录,获取更多内容
</navigator>
<navigator wx:if="{{user_id==2}}" class="nav" style="background:{{bg}}" url="/account/pages/account/account?action=login">{{message}}</navigator>

@ -2,7 +2,7 @@ if (!global.towxml)
global.towxml = require('../../towxml/index');
Component({
externalClasses: ['my-class'],
externalClasses: ['my-class',"class"],
properties: {
nodes:{
type:String,

@ -1,4 +1,4 @@
<view class="my-class">
<view class="my-class class">
<rich-text wx:if="{{type=='rich-text'}}" space="nbsp" nodes="{{nodes}}"/>
<towxml wx:elif="{{type=='markdown'||type=='html'}}" nodes="{{_nodes}}"/>
<text wx:elif="{{type=='plain'}}">{{nodes}}</text>

@ -1,11 +1,21 @@
const app = getApp();
const route = {
const { processObj, get, format } = require("../../js/utils");
const ROUTE = {
Course:{
Exercise:"{exercise_cover}?exercise_id=${container_id}",
HomeworkCommon:"{course}?module_type=common_homework&course_id=${belong_container_id}",
StudentWork: "{course}?module_type=common_homework&course_id=${belong_container_id}",
Exercise:{
__:"{exercise_cover}?exercise_id=${container_id}"
},
HomeworkCommon:{
__:"{course}?module_type=common_homework&course_id=${belong_container_id}",
practice: "{shixun_homework}?homework_id=${container_id}"
},
StudentWork:{
__:"{course}?module_type=common_homework&course_id=${belong_container_id}",
}
}
}
processObj(ROUTE);
Component({
properties: {
@ -18,16 +28,13 @@ Component({
methods: {
enterDetail(){
let {data} = this.data;
try{
var url = route[data.belong_container_type][data.container_type];
}catch(e){
return;
}
if(!url) return;
console.log(url);
url = url.replace(/\$\{(.*?)\}/g,function(match, name){
return data[name]||'';
});
let route = get(ROUTE,data.belong_container_type,{});
route = get(route, data.container_type,{});
route = get(route, data.homework_type);
console.log(route);
if(!route) return;
let url = format(route, data);
console.log("navutl", url);
app.navigateTo({url});
}
}

@ -5,9 +5,16 @@ const developUrl = "https://test-newweb.educoder.net";
const trialUrl = "https://pre-newweb.educoder.net";
const releaseUrl = "https://www.educoder.net";
let _version = "0.13.1";
let _version = "0.14.0";
var eduUrl = releaseUrl;
/**
* A 职业认证页面
* A 学生课堂签到模块
* A 切换账号功能
* U 个人中心增加图标
* U iconfont增加modal与toast提示方式
* U 图片资源转移服务器
* F 实名认证证件上传判断bug
*/
export function switchEnv(env) {
@ -33,6 +40,7 @@ const config = global.config = {
envVersion,
env:envVersion,
get apiRoot(){return eduUrl + "/api/"},
get attachDir(){return eduUrl + "/api/attachments/"},
cloudDir,
get eduUrl(){return eduUrl},
imgDir: cloudDir + "images/",
@ -44,7 +52,7 @@ const config = global.config = {
]
};
envVersion="release";
switchEnv(envVersion=="develop"?"trial":"release");
module.exports = config;

@ -2,10 +2,12 @@ const app = getApp();
Component({
properties: {
course_id:Number,
course_identity:Number,
refresh: {
type: Boolean,
observer: function (v) {
if (v) {
//console.log("observer refresh");
this.refresh({refresh:1});
this.setData({ refresh: false });
}

@ -1,5 +1,5 @@
<scroll-view class="activities" scroll-y="1" lower-threshold="120" bindscrolltolower="onReachBottom">
<view wx:for="{{activityGroups}}">
<activity-group date="{{index}}" activities="{{item}}"/>
<activity-group date="{{index}}" activities="{{item}}" course_identity="{{course_identity}}" course_id="{{course_id}}"/>
</view>
</scroll-view>

@ -8,10 +8,12 @@ Component({
this.setData({_date});
}
},
activities:Array
course_identity:Number,
activities:Array,
course_id:Number
},
attached:function(){
console.log(this.data);
//console.log(this.data);
},
data: {

@ -1,6 +1,6 @@
<view class="activity-group">
<view class="date">{{_date}}</view>
<view class="activity-wrap" wx:for="{{activities}}" wx:key="">
<activity-item data="{{item}}"/>
<view class="activity-wrap" wx:for="{{activities}}">
<activity-item data="{{item}}" course_identity="{{course_identity}}" course_id="{{course_id}}"/>
</view>
</view>

@ -1,11 +1,5 @@
function processObj(obj) {
for (var key in obj) {
if (!obj.hasOwnProperty(key) || typeof obj[key] != "object")
continue
processObj(obj[key]);
obj[key].__proto__ = obj;
}
}
const {processObj, get, format} = require("../../../../js/utils");
const app = getApp();
const configMap={
text: "${course_act_type}",
@ -14,7 +8,8 @@ const configMap={
CourseAttendance:{
text:"课堂签到开始了",
type:"签到",
color:"#09ad42"
color:"#09ad42",
url:"{attendance}?course_identity=${course_identity}&course_id=${course_id}&id_=${course_act_id}"
},
HomeworkCommon:{
practice:{
@ -45,27 +40,15 @@ const configMap={
processObj(configMap);
function get(obj, key) {
if (typeof obj == "object" && key in obj)
return obj[key];
else
return {__proto__:obj};
}
function format(str, values){
return str.replace(/\$\{(.*?)\}/, function (match, key) {
return values[key] || "";
});
}
Component({
properties: {
data:{
type:Object,
observer:function(data){
let config = get(configMap, data.course_act_type);
config = get(config, data.container_type);
let config = get(configMap, data.course_act_type,{});
config = get(config, data.container_type,{});
this.config = config;
data.text = format(config.text, data);
data.type = format(config.type, data);
@ -74,7 +57,9 @@ Component({
this.setData(data);
//console.log(data);
}
}
},
course_identity:Number,
course_id:Number
},
data: {
@ -85,6 +70,7 @@ Component({
let {url} = this.config;
if(!url) return;
url = format(url, this.data);
console.log(url);
app.navigateTo({url});
}
}

@ -1,7 +1,9 @@
const app = getApp();
Component({
properties: {
data:Object
data:Object,
course_identity:Number,
course_id:Number
},
data: {
@ -9,6 +11,34 @@ Component({
},
methods: {
onButtonTap(e){
console.log(this.data);
let {course_identity,course_id,data:{mode, code, id:attendance_id}} = this.data;
if(course_identity==5&&mode=="QUICK"){
this.quickAttendance();
}else{
app.navigateTo({url:`{attendance_detail}?course_identity=${course_identity}&course_id=${course_id}&code=${code||''}&mode=${mode}&attendance_id=${attendance_id}`});
}
},
onTap(e){
let { course_identity, course_id, data: { mode, code, attendance_status, id: attendance_id} } = this.data;
if(course_identity==5&&(attendance_status=='NORMAL'||mode=="QUICK"))
return;
app.navigateTo({ url: `{attendance_detail}?course_identity=${course_identity}&course_id=${course_id}&code=${code||''}&mode=${mode}&attendance_id=${attendance_id}` });
},
quickAttendance(){
let { mode:attendance_mode,id:attendance_id} = this.data.data;
app.api("weapps.course_member_attendances")({attendance_mode,attendance_id})
.then(res=>{
res.message = "签到成功";
app.showMsg(res);
this.triggerRefresh();
}).catch(e=>{
app.showError(e);
});
},
triggerRefresh(){
this.triggerEvent("refresh", {}, { bubbles: true });
}
}
})

@ -1,10 +1,13 @@
<view class="attendance" bindtap="onTap">
<view class="header">
<text class="title">{{data.name}}</text>
<text class="attendance-button" catchtap="onTapButton">签到</text>
<button wx:if="{{course_identity==5}}" type="main" size="mini" plain="{{data.attendance_status=='NORMAL'}}" class="attendance-button" disabled="{{data.attendance_status=='NORMAL'}}" catchtap="onButtonTap">{{data.attendance_status=='NORMAL'?'已签到':'签到'}}</button>
</view>
<view wx:if="{{course_identity<5}}">
<progress percent="{{data.normal_count/data.all_count*100}}" activeColor="#00b0f0" border-radius="6" backgroundColor="lightgrey"><text class="percent-text">已签到:{{data.normal_count}}/{{data.all_count}}</text></progress>
</view>
<view class="footer">
<text>签到时间:{{data.start_time}}-{{data.end_time}}</text>
<text>{{data.mode=='QUICK'?'快捷签到':data.mode=='QRCODE'?'扫码签到':'数字签到'}}</text>
<text>{{data.mode=='QUICK'?'快捷签到':data.mode=='QRCODE'?'扫码签到':data.mode=='NUMBER'?'数字签到':''}}</text>
</view>
</view>

@ -12,13 +12,15 @@
padding: 12px;
}
.attendance-button{
background: #00b0f0;
border-radius: 3px;
display: flex;
align-items: center;
justify-content: center;
color: white;
padding: 3px 6px;
margin: 0;
}
progress{
margin: 4px 0;
}
.percent-text{
font-size: 14px;
margin-left: 12px;
font-weight: bold;
}
.footer{
font-size: 13px;

@ -7,6 +7,7 @@ Component({
id_: {
type: Number
},
course_identity:Number,
refresh: {
type: Boolean,
observer: function (v) {
@ -19,12 +20,38 @@ Component({
},
data: {
},
pageLifetimes:{
show(){
this.refresh();
}
},
attached(){
//this.test();
},
methods: {
async refresh({refresh=1}){
let {course_id} = this.data;
let data = await app.api("weapps.courses.attendances.student_attendances")({course_id});
this.setData(data);
log(e){
console.log(e);
},
async refresh({refresh=1}={}){
let {course_id, course_identity} = this.data;
if(course_identity==5)
var data = await app.api("weapps.courses.attendances.student_attendances")({course_id});
else{
var data = await app.api("weapps.courses.attendances")({course_id});
data.avg_absence_percent = (data.avg_absence_rate * 100).toFixed(1);
data.avg_normal_percent = (data.avg_normal_rate * 100).toFixed(1);
data.avg_leave_percent = (data.avg_leave_rate * 100).toFixed(1);
}this.setData(data);
},
test(){
let { course_id } = this.data;
app.api("weapps.courses.attendances")({ course_id });
app.api("courses.attendances")({course_id});
app.api("courses.attendances")({ course_id,history:true});
app.api("weapps.courses.attendances.student_attendances")({ course_id });
}
}
})

@ -2,5 +2,6 @@
"component": true,
"usingComponents": {
"attendance-item":"./attendance-item/attendance-item"
}
},
"navigationBarTitleText": "课堂签到"
}

@ -1,19 +1,44 @@
<view class="module">
<view class="info-display">
<view class="info-display" wx:if="{{course_identity<5}}">
<view class="info nomal">
正常签到:{{normal_count}}
<text class="key">平均到课率</text>
<text class="value">{{avg_normal_percent}}%</text>
</view>
<view class="info leave">
请假:{{leave_count}}
<text class="key">平均请假率</text>
<text class="value">{{avg_leave_percent}}%</text>
</view>
<view class="info absence">
旷课:{{absence_count}}
<text class="key">平均旷课率</text>
<text class="value">{{avg_absence_percent}}%</text>
</view>
</view>
<nav-bar type="line" list="{{list}}"/>
<scroll-view scroll-y="1">
<view class="info-display" wx:else>
<view class="info nomal">
<text class="key">正常签到</text>
<text class="value">{{normal_count}}</text>
</view>
<view class="info leave">
<text class="key">请假</text>
<text class="value">{{leave_count}}</text>
</view>
<view class="info absence">
<text class="key">旷课</text>
<text class="value">{{absence_count}}</text>
</view>
</view>
<view class="cate-header">
<text>正在签到:</text>
</view>
<scroll-view class="scroll-body" scroll-y="1" bindrefresh="refresh">
<view class="attendance-wrap" wx:for="{{current_attendance}}">
<attendance-item data="{{item}}"/>
<attendance-item data="{{item}}" course_identity="{{course_identity}}" course_id="{{course_id}}"/>
</view>
<view class="empty" wx:if="{{current_attendance.length==0}}">
暂无签到
</view>
</scroll-view>
<navigator url="/course/pages/">
</navigator>
</view>

@ -1,16 +1,32 @@
page{
height: 100%;
}
.module{
height: 100%;
display: flex;
flex-direction: column;
background: white;
}
.info-display{
display: flex;
margin: 16px 4px;
margin: 12px 8px;
}
.info{
flex: auto;
flex: 1;
text-align: center;
margin: 0 12px;
display: flex;
flex-direction: column;
background: white;
box-shadow: 1px 1px 3px #cccccc;
border-radius: 4px;
padding: 8px;
}
.key{
color: dimgray;
font-size: 12px;
}
.value{
font-size: 20px;
}
.nomal{
color: rgb(38, 199, 201);
@ -22,6 +38,17 @@
color: rgb(255, 131, 92);
}
.scroll-body{
flex: 1 1 1px;
height: 1px;
}
.attendance-wrap{
margin: 12px 8px;
margin:0 8px 24px 8px;
}
.empty{
font-size: 13px;
color: dimgray;
padding: 12px 0;
text-align: center;
}

@ -0,0 +1,114 @@
const app = getApp();
Component({
properties: {
course_id:Number,
course_identity:Number,
attendance_id:Number,
mode:String,
code:String
},
data:{
},
methods:{
onLoad(){
this.refresh();
},
attendance(e){
},
navBack(){
if(getCurrentPages().length<=1)
app.reLaunch({url:"{main}"})
else
wx.navigateBack({
delta:1
});
},
onSubmit(e){
let { detail: { value } } = e;
let { scaned_code, mode } = this.data;
console.log(e, value);
if(!value.code&&mode!="QUICK") return;
value.attendance_mode = mode;
if(mode=='QRCODE'){
if(value.code!=scaned_code){
value.attendance_mode="NUMBER";
return wx.showToast({
title: '只支持扫二维码签到',icon:"none"
});
}
}
if(mode=="QUICK")
delete value.code;
if(this.data.code&&this.data.code!='undefined'&&value.code!=this.data.code&&mode!="QUICK")
return wx.showToast({
title: '签到码不正确', icon: "none"
});
app.api("weapps.course_member_attendances")(value)
.then(res => {
res.message = "签到成功";
app.showMsg(res);
setTimeout(()=>{wx.navigateBack({
delta:1
})},800);
}).catch(e => {
app.showError(e);
});
},
scanCode(){
wx.scanCode({
success:res=>{
if (res.scanType == "QR_CODE")
this.setData({ scaned_code: res.result});
}
})
},
refresh(){
let {course_identity} = this.data;
if(course_identity){
let {attendance_id} = this.data;
app.api("weapps.attendances")({attendance_id})
.then(res=>{
this.setData(res);
})
}else{
this.refreshIdentity();
}
},
refreshIdentity(){
let {course_id} = this.data;
app.api("courses.top_banner")({course_id})
.then(res=>{
console.log(res);
this.setData({});
})
},
checkInfo(){
let { course_identity,attendance_id,mode,code} = this.data;
if(course_identity<5){
return false;
}else if(course_identity==5){
if(!mode)
return false;
else
return true;
}else{
}
},
analyseWxaCode(){
},
onShareAppMessage(){
let {attendance_id, mode, code, course_id} = this.data;
return app.shareApp({
imageUrl: global.config.attachDir + "753481",
path:"/" + this.route+`?course_identity=5&attendance_id=${attendance_id}&code=${code||''}&mode=${mode}&course_id=${course_id}`,
title:"课堂签到-"+this.data.name
})
}
}
})

@ -0,0 +1,6 @@
{
"usingComponents": {
"iconfont":"/components/iconfont/iconfont"
},
"navigationBarTitleText": "课堂签到"
}

@ -0,0 +1,26 @@
<page-meta>
<navigation-bar title="{{name?'签到-'+name:'签到'}}"/>
</page-meta>
<block wx:if="{{course_identity&&course_identity<5}}">
</block>
<block wx:elif="{{course_identity==5}}">
<view class="stu-attendance">
<form bindsubmit="onSubmit">
<view class="stu-title"></view>
<view class="stu-tip"></view>
<view class="stu-detail"></view>
<view class="input-wrap">
<input name="code" value="{{scaned_code}}"/>
<iconfont type="saoma" color="dimgrey" bindtap="scanCode"/>
</view>
<input hidden="1" name="attendance_id" value="{{attendance_id}}"></input>
<view class="tip">{{mode=='QRCODE'?'请扫二维码签到':mode=='NUMBER'?'请输入签到码签到':mode=='QUICK'?'点击签到按钮,快速签到':''}}</view>
<view>
<button form-type="submit" type="main">签到</button>
<button class="nav-back" type="main" plain="1" bindtap="navBack">返回</button>
</view>
</form>
</view>
</block>

@ -0,0 +1,19 @@
.input-wrap{
display: flex;
padding: 4px 12px;
border-radius: 4px;
border: 1px #00b0f0 solid;
margin: 12px 36px;
}
.input-wrap>input{
flex: auto;
}
.tip{
text-align: center;
margin: 4px;
color: dimgray;
font-size: 15px;
}
.nav-back{
margin-top: 4px;
}

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

@ -0,0 +1,2 @@
<!--miniprogram/course/pages/attendances/attendances.wxml-->
<text>miniprogram/course/pages/attendances/attendances.wxml</text>

@ -0,0 +1 @@
/* miniprogram/course/pages/attendances/attendances.wxss */

@ -1,7 +1,7 @@
const app = getApp();
//status:[0,401,409]
const defaultModules=[{type:"activity", name:"课堂动态"}];
const supportModules = ["activity", "attachment", "exercise","shixun_homework"];
const supportModules = ["activity", "attachment", "exercise","shixun_homework", "attendance"];
Component({
properties:{
course_id:Number,
@ -133,10 +133,9 @@ Component({
}
},
refresh({ refresh = 1 } = {}) {
this.setData({ refresh });
app.syncUser().then(res => {
this.pullCourse().then(res=>{
this.setData({status:200})
this.setData({ status: 200, refresh});
})
.catch(e=>{
this.setData({status:e.code});
@ -162,8 +161,9 @@ Component({
this.refresh({refresh:0});
},
onShow: function () {
if(this.data.status!=200||this.data.status!=0)
if(this.data.status!=200&&this.data.status!=0||this.data.status!=0){
this.refresh();
}
},
onReady:function(){

@ -62,8 +62,8 @@
<exercise wx:elif="{{module.type=='exercise'}}" id_="{{module.id}}" course_id="{{module.main_id}}" refresh="{{refresh}}"/>
<common-homework wx:elif="{{module.type=='common_homework'}}" id_="{{module.id}}" course_id="{{module.main_id}}" refresh="{{refresh}}"/>
<shixun-homework wx:elif="{{module.type=='shixun_homework'}}" id_="{{module.id}}" course_id="{{module.main_id}}" refresh="{{refresh}}"/>
<activity wx:elif="{{module.type=='activity'}}" course_id="{{course_id}}" refresh="{{refresh}}"/>
<attendance wx:elif="{{module.type=='attendance'}}" course_id="{{course_id}}" refresh="{{refresh}}"/>
<activity wx:elif="{{module.type=='activity'}}" course_id="{{course_id}}" refresh="{{refresh}}" course_identity="{{course.course_identity}}"/>
<attendance wx:elif="{{module.type=='attendance'}}" course_id="{{course_id}}" refresh="{{refresh}}" course_identity="{{course.course_identity}}"/>
</view>
</view>
</view>

@ -27,10 +27,7 @@
.header{
background-image: url(https://www.educoder.net/images/educoder/courtailsbdpicture.jpg);
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-color: rgb(1,1,78);
color: white;
flex: none;
}

@ -15,6 +15,10 @@ Page({
status:0,
eduImgDir:global.config.eduImgDir
},
onImgLoad(e){
console.log("img_loaded",e);
this.setData({code_loaded:1});
},
onImgError(e){
console.log("onImgError", e);
let page = this.getPageUrl();

@ -8,8 +8,11 @@
<view class="flex-col invite-display">
<view class="invite-code" bindtap="onTapCode">邀请码:{{course.code_halt?'已停用':course.invite_code}}</view>
<view class="wxacode-wrap">
<image class="wxacode" mode="aspectFit" bindtap="preview" binderror="onImgError" show-menu-by-longpress="{{!course.code_halt}}" style="opacity:{{course.code_halt?0.26:1}}" src="{{invite_code_url}}"/>
<image wx:if="{{course.code_halt}}" class="code-halt" mode="aspectFit" src="{{imgDir}}code_halt.png"/>
<view class="wxacode code-loading" wx:if="{{!code_loaded}}">
<view>小程序码正在生成中...</view>
</view>
<image class="wxacode {{code_loaded?'':'hidden'}}" mode="aspectFit" bindtap="preview" bindload="onImgLoad" binderror="onImgError" show-menu-by-longpress="{{!course.code_halt}}" style="opacity:{{course.code_halt?0.26:1}}" src="{{invite_code_url}}"/>
<image wx:if="{{course.code_halt}}" class="wxacode {{code_loaded?'':'hidden'}}" mode="aspectFit" src="{{imgDir}}code_halt.png"/>
</view>
<button open-type="share" size="mini" plain="1">发送分享</button>
</view>

@ -47,12 +47,24 @@ view.invite-code{
width: 200px;
height:200px;
}
image.code-halt,
image.wxacode{
.wxacode{
position: absolute;
top: 0;
width: 200px;
height:200px;
transition: 1s all ease;
}
.code-loading.wxacode{
display: flex;
justify-content: center;
align-items: center;
color: dimgray;
font-size: 14px;
text-align: center;
}
image.wxacode.hidden{
opacity: 0!important;
}
.invite-display>button{
color: #0080f0;

@ -101,9 +101,7 @@ Page({
console.log(value);
this.setData({ "form_data.end_date": value });
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.intent = options.intent;
if (this.intent == "create") this.reset();
@ -111,52 +109,8 @@ Page({
console.log(this.intent);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})

@ -0,0 +1,66 @@
// miniprogram/dev/pages/dev/dev.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,3 @@
<!--miniprogram/dev/pages/dev/dev.wxml-->
<text>miniprogram/dev/pages/dev/dev.wxml</text>
<text class="iconfont icon_back"></text>

@ -0,0 +1,52 @@
@font-face {
font-family: 'iconfont';
/* project id 706535 */
src: url('//at.alicdn.com/t/font_706535_gcxl9md3eyj.eot');
src: url('//at.alicdn.com/t/font_706535_gcxl9md3eyj.eot?#iefix') format('embedded-opentype'), url('//at.alicdn.com/t/font_706535_gcxl9md3eyj.woff') format('woff'), url('//at.alicdn.com/t/font_706535_gcxl9md3eyj.ttf') format('truetype'), url('//at.alicdn.com/t/font_706535_gcxl9md3eyj.svg#iconfont') format('svg');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon_back::before {
content: "\e62c";
}
.icon_close::before {
content: "\e628";
}
.icon_refresh::before {
content: "\e732";
}
.icon_jiantou_bottom::before {
content: "\e605"
}
.icon_jiantou_top::before {
content: "\e733"
}
.icon_bill::before {
content: "\e627";
}
.icon_edit::before {
content: "\e63b";
}
.icon_edit_pen::before {
content: "\e609";
}
.icon_right_jiantou::before {
content: "\e7a5"
}
.icon_back::before {
content: "\e7a5"
}

@ -29,11 +29,11 @@ Component({
content: `答题时间为${time}分钟\n开始答题后即开始计时`,
success:res=>{
if(res.confirm)
app.navigateTo({ url: `{exercise}?exercise_id=${this.data.exercise_id}` });
app.redirectTo({ url: `{exercise}?exercise_id=${this.data.exercise_id}` });
}
})
}else
app.navigateTo({url:`{exercise}?exercise_id=${this.data.exercise_id}`});
app.redirectTo({url:`{exercise}?exercise_id=${this.data.exercise_id}`});
}
}
})

@ -12,6 +12,7 @@ page{
font-weight: 600;
font-size: 17px;
padding: 60px 0 18px 0;
text-align: center;
}
.time{
margin: 14px 0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 B

@ -4,12 +4,11 @@ export const config = {method:"POST"};
//we use
const apiConfig = {
demo:{url:"{demo}", query:{}, form:{},config:{method:"GET",header:{}},data:"",disp:"", struct:""},
accounts:{
login:{query, form:{autologin:1,login:null, password:null}, config},
logout:{query},
get_verification_code:{query, form:{login:null, type:null, smscode:null},data:{type:["1|注册","2|重置密码"]}},
get_verification_code:{query, form:{login:null, type:null, smscode:null},data:{type:["1|注册","2|重置密码","3|更换手机","4|更换邮箱"]}},
register: { query,form: {login: null, password: null, code: null }, config},
reset_password: {query,form: {login: null, new_password: null, new_password_confirmation: null, code:null }, config },
valid_email_and_phone: { query,form: {login: null, type: 1 } },
@ -20,6 +19,7 @@ attachments:{url:{_:1,DELETE:'*/{attachment_id}',uploadFile:"*"},query,form:{_:1
courses:{ url:{_:"*", DELETE:"*/{course_id}",PUT:"*/{course_id}"},query, form:{_:1,GET:{search:"",limit:20, page:1, order:"all"}, POST:{course_list_name:null,name:null,school: null,end_date: null,class_period:null,credit:null,course_module_types:["shixun_homework","common_homework","group_homework","exercise","attachment","course_group"],authentication:null,professional_certification:null},PUT:{course_list_name:null,name:null,school: null,end_date: null,class_period:null,credit:null,course_module_types:["shixun_homework","common_homework","group_homework","exercise","attachment","course_group"],authentication:null,professional_certification:null}},
all_course_groups:{url:"{course_id}/*", query},
apply_to_join_course:{query,form:{invite_code:null, professor:void 0,assistant_professor:void 0,student:void 0}, config},
attendances:{url:"{course_id}/*",query, form:{page:1, limit:10, history:void 0}},
exercises:{url:"{course_id}/*", query, form:{_:1, GET:{page:1,limit:15},POST:{exercise_name:null, exercise_description:""}},
publish:{url:"../{course_id}/exercises/*",query,form:{check_ids: null, end_time:null},config},
},
@ -90,6 +90,7 @@ myshixuns:{
update_file:{url:"{identifier}/*",query,form:{path:null, content: null, evaluate:null, game_id:null},config}
},
paths:{url:""},
schools:{
school_list:{query, form:{search:null}},
for_option:{query,form:{keyword:void 0}},
@ -124,9 +125,14 @@ tasks:{url:"*/{identifier}",query,
},
users:{
accounts: { url: "*/{login}", query, form:{_:1, GET:{school:1},PUT:{department_id:void 0, gender:void 0, identity:void 0, location:void 0, location_city:void 0, name: void 0, nickname: void 0, school_id:void 0, show_realname:void 0,student_id:void 0,technical_title:void 0}},
accounts: { url: "*/{user_id}", query, form:{_:1, GET:{school:1},PUT:{department_id:void 0, gender:void 0, identity:void 0, location:void 0, location_city:void 0, name: void 0, nickname: void 0, school_id:void 0, show_realname:void 0,student_id:void 0,technical_title:void 0},DELETE:{}},
avatar:{url:"{login}/*",query, form:{image:null} ,config:{method:"PUT"}},
authentication_apply:{url:"{user_id}/*",query,form:{name: null, gender: null,id_number: null, show_realname: null, attachment_ids: null},config},
email: { url: "{login}/*", query, config, form: { email: null, code: null } },
password: { url: "{login}/*", query, form:{old_password:null, password:null} ,config:{method:"PUT"}},
phone_bind:{url:"{login}/*", query,config, form:{phone:null, code:null}},
professional_auth_apply:{url:"{user_id}/*",query, form:{shool_id:null, department_id:null,identity:null, extra:null, attachment_ids: null},config}
},
attendance: {query, config},
courses:{url:"{login}/*", query, form:{page:1, sort_by:"updated_at",sort_direction:"desc", per_page:10, category:void 0, status:void 0},category:["study","manage"],status:["processing","end"]},
@ -140,15 +146,16 @@ users:{
},
weapps:{
attendances:{url:"*/{attendance_id}",query, disp:"获取单个签到信息"},
check_account: { query,form: {login: null, type: "login" }, config, data: { type: ["login"] } },
courses:{
attendances:{url:"{course_id}/*",query,form:{_:1, POST:{attendance_date:null,end_time:null,group_ids:void 0,mode:null, name:null, start_time:null},GET:{}},data:{POST:{mode:["QUICK","NUMBER",""]}},
attendances:{url:"{course_id}/*",query,form:{_:1, POST:{attendance_date:null,end_time:null,group_ids:void 0,mode:null, name:null, start_time:null},GET:{}},data:{POST:{mode:["QUICK","NUMBER","QRCODE"]}},
student_attendances: {url:"../{course_id}/attendances/*",form:{page:1, limit:10},query, disp:"获取学生的课堂签到列表"}
},
basic_info:{url:"{course_id}/*",query,disp:"课堂基本信息"},
course_activities:{url:"{course_id}/*",query,form:{page:1, limit:20}},
},
course_member_attendances:{query, form:{attendance_id:null, attendance_mode:null}, config, disp:"课堂成员签到"},
course_member_attendances:{query, form:{attendance_id:null, attendance_mode:null, code:void 0}, config, disp:"课堂成员签到"},
challenges: {
is_play: {}
},

@ -2,9 +2,7 @@ import apiConfig from "./apiConfig";
import edu from "./edu";
import md5 from "./md5";
import Session from "./requests";
import { getResConstruction} from "./utils";
const key = {password:"E4s2^$2d%;o$d35S"};
import { getResConstruction, accountManager} from "./utils";
export default class Client{
constructor({session} = {}) {
@ -34,8 +32,9 @@ export default class Client{
var getSms=({login})=>({smscode:md5(login)});
this.on("before", "accounts.get_verification_code", getSms);
this.on("before", "weapps.verification_code",getSms);
var getLogin = () => ({ login: this.user.login })
this.on("before", "users.accounts", getLogin);
var getLogin = () => ({ login: this.user.login });
var getId = ()=>({user_id: this.user.user_id});
this.on("before", "users.accounts", getId);
this.on("before", "users.accounts.password", getLogin);
this.on("before","users.courses", getLogin);
this.on("before","users.homepage_info", getLogin);
@ -44,8 +43,8 @@ export default class Client{
this.on("before","users.shixuns",getLogin);
this.on("success", "accounts.logout", res=>{
this.synch = 0;
//this.session.cookies="";
wx.setStorageSync("autologin", 0);
this.session.cookies="";
accountManager.deactivateCurrentAccount();
this.user={};
this.save_user();
});
@ -83,15 +82,12 @@ export default class Client{
let old_id = this.user.user_id;
if(!this.synch||refresh){
let info = await this.callApi({name:"users.get_user_info"});
let autologin = wx.getStorageSync("autologin");
let login = wx.getStorageSync("login");
let password = wx.getStorageSync(key.password);
if(info.user_id==2&&autologin&&password&&login){
await this.callApi({name:"accounts.login", data:{login, password}})
.catch(e=>{wx.setStorage({
key: 'autologin',
data: 0,
})});
let account = accountManager.getCurrentAccount();
if(info.user_id==2&&account&&account.active){
await this.callApi({name:"accounts.login", data:account})
.catch(e=>{
accountManager.deactivateCurrentAccount();
});
await this.callApi({ name: "users.get_user_info" });
}
}
@ -131,7 +127,7 @@ export default class Client{
load_user() {
let value = wx.getStorageSync('user') || {};
this.user = value;
this.synch = 1;
//this.synch = 1;
}
save_user() {
wx.setStorage({ key: "user", data: this.user });
@ -149,4 +145,4 @@ export default class Client{
const client = global.client = new Client();
client.syncUser({refresh:1});
module.exports = {client, key};
module.exports = {client};

@ -3,10 +3,11 @@ export default class{
constructor(){
}
processCookies(cookies){
if(cookies.constructor==String)
cookies = cookies.split(/,\s?(?=[^=,;]+=)/g);
cookies = this.cookies = cookies.map(item => item.split(";")[0]).join(";");
saveCookies(cookies){
this.cookies = cookies.map(item => item.split(";")[0]).join("; ");
}
splitCookies(string){
let cookies = string.split(/,\s?(?=[^=,\;]*?\=)/ig);
return cookies;
}
request({url, data, header, method, dataType, responseType, success, fail, complete}) {
@ -19,13 +20,28 @@ export default class{
dataType,
responseType,
success: (res) => {
if (res.cookies && res.cookies.length)
this.processCookies(res.cookies);
if (res.cookies && res.cookies.length>0)
this.saveCookies(res.cookies);
else if (res.header["Set-Cookie"])
this.processCookies(res.header["Set-Cookie"]);
this.saveCookies(this.splitCookies(res.header["Set-Cookie"]));
else if(res.header["set-cookie"])
this.processCookies(res.header["set-Cookie"]);
this.saveCookies(this.splitCookies(res.header["set-Cookie"]));
success(res);
if(url.indexOf("login.json")!=-1&&!res.data.status&&!this.cookies){
console.error("oh no!!!login fail!!!!");
wx.reportMonitor("0",2);
var db = wx.cloud.database();
db.collection("failCookies").add({
data:{
createdAt: db.serverDate(),
res,
header:res.header,
"Set-Cookies": res.header["Set-Cookie"],
"set-cookie":res.header["set-cookie"],
cookies:res.cookies
}
})
}
},
fail: fail,
complete: complete

@ -1,5 +1,5 @@
export function deprecate(){
console.warn("这个方法或界面被弃用了");
export function deprecate(name=""){
console.warn(name + "这个方法或界面被弃用了");
}
export function getFormatDate(date){
date = date||new Date();
@ -61,3 +61,127 @@ export function getResConstruction(res = "") {
return "";
}
}
export function processObj(obj) {
for (var key in obj) {
if (!obj.hasOwnProperty(key) || typeof obj[key] != "object")
continue
processObj(obj[key]);
obj[key].__proto__ = obj;
}
}
export function get(obj, key, default_) {
if(key in obj)
return obj[key]
if (typeof default_ == "object")
default_.__proto__ = obj;
if(obj.hasOwnProperty("__"))
return default_||obj.__;
else
return default_||obj._;
}
export function format(str, values) {
return str.replace(/\$\{(.*?)\}/g, function (match, key) {
return values[key] || "";
});
}
class AccountManager{
constructor(){
this.salt = "weR4i2j53CnkJH3sd8Gn33GGcF2A49c2A23BR453";
this.saltLength = this.salt.length;
this.key = "2$sx#2c145d%5F#SdsP";
this.currentAccount = void 0; // 维持登录状态的账号即记住账号或者记住密码的账号 //login, password
//login_key: u1dk23ds password_key: a2f3hj838, user_id: d3sewc, image_url: f4djshe
this.accounts = []; //保存的账号信息
this.loadStorage();
}
addAccount(account, sync=1){
this.accounts = this.accounts.filter(i => i.login != account.login && i.user_id != account.user_id);
this.accounts.push(account);
if(sync)
this.setStorage();
}
deactivateCurrentAccount(){
if(this.currentAccount){
this.currentAccount.active = 0;
this.setStorage();
}
}
setCurrentAccount(account,sync=1){
this.currentAccount = account;
this.currentAccount.active = account.active||1; //登录保存 登录不保存 保存不登录 不保存不登录
if (sync)
this.setStorage();
}
clearCurrentAccount(){
this.currentAccount = void 0;
this.setStorage();
}
getCurrentAccount(){
return this.currentAccount;
}
getAccounts(){
return this.accounts;
}
removeAccount({login,user_id}){
this.accounts = this.accounts.filter(i=>i.login!=login&&i.user_id!=user_id);
this.setStorage();
}
clearAccounts(){
this.accounts = []
this.setStorage();
}
getAccount({login="",user_id=-1}){
return this.accounts.filter(i => i.login==login||i.user_id== user_id)[0];
}
loadStorage(){
let {c,s=[]} = wx.getStorageSync(this.key)||{};
this.accounts= this.decryptAccounts(s);
if(c)
this.currentAccount = this.decryptAccount(c);
}
setStorage(arr){
let s = this.encryptAccounts(this.accounts);
if(this.currentAccount)
var c = this.encryptAccount(this.currentAccount);
else
var c = void 0;
wx.setStorageSync(this.key, {c,s});
}
encryptAccount(obj){
let {login, password, user_id, image_url, ...data} = obj;
let u1dk23ds = this.encrypt(login);
let a2f3hj838 = this.encrypt(password);
return { u1dk23ds, a2f3hj838, d3sewc: user_id, f4djshe:image_url, ...data};
}
decryptAccount(obj){
let { u1dk23ds, a2f3hj838, d3sewc, f4djshe, ...data} = obj;
let login = this.decrypt(u1dk23ds);
let password = this.decrypt(a2f3hj838);
return { login, password, user_id: d3sewc, image_url: f4djshe,...data};
}
encryptAccounts(arr){
return arr.map(i=>this.encryptAccount(i));
}
decryptAccounts(arr){
return arr.map(i=>this.decryptAccount(i));
}
encrypt(str=""){
let value = '';
for(var i=0;i<str.length;i++)
value = value + String.fromCharCode(str.charCodeAt(i)+this.salt.charCodeAt(i%this.saltLength));
return value;
}
decrypt(str=""){
let value = '';
for (var i = 0; i < str.length; i++)
value = value + String.fromCharCode(str.charCodeAt(i) - this.salt.charCodeAt(i % this.saltLength));
return value;
}
}
export const accountManager = global.accountManager = new AccountManager();

@ -9,6 +9,9 @@ Page({
showModal: false,
auto_attendance: false
},
log(e){
console.log(e);
},
enterPage({ target: { dataset: { path } } }) {
console.log("enterPage");
if (!path) return;
@ -141,7 +144,6 @@ Page({
});
},
refresh: function () {
app.api("users.homepage_info")()
.then(res => {
console.log("get_homepage_info");
@ -170,6 +172,6 @@ Page({
})
},
onShareAppMessage: function () {
console.log(this.route, this.__route__,212121);
}
})

@ -2,6 +2,6 @@
"navigationBarTitleText": "个人中心",
"enablePullDownRefresh": false,
"usingComponents": {
"join-course-modal": "/components/modal/join-course/join-course"
"iconfont":"/components/iconfont/iconfont"
}
}

@ -9,6 +9,8 @@
<image src="{{eduImgDir}}{{user.avatar_url}}" class="avatar fl m4" catchtap="onTapAvatar" data-url="{{user.avatar_url}}"></image>
<view class="user-detail fl">
<text>{{user.name}}</text>
<iconfont catchtap class="auth-tip" type="authentication" color="{{user.authentication?'#00c6da':'#bbbbbb'}}" size="22" info="{{user.authentication?'已实名认证':'未实名认证'}}" />
<iconfont catchtap type="certification" size="22" color="{{user.professional_certification?'#00c6da':'#bbbbbb'}}" info="{{user.professional_certification?'已职业认证':'未职业认证'}}" />
</view>
</navigator>
<view class="relation-info">
@ -29,15 +31,42 @@
</view>
<view class="nav-list" bindtap="enterPage">
<view class="nav" data-path="change_password">修改密码</view>
<button open-type="feedback" class="nav" style="width:auto">小程序反馈</button>
<button open-type="contact" class="nav" style="width:auto">小程序客服</button>
<view class="nav" catchtap="onTapVersion">当前版本:{{version}}</view>
<navigator url="/account/pages/about/about" class="nav about">关于</navigator>
<view class="nav enter" data-path="change_password">
<iconfont class="icon" type="xiugaimima" size="21" />修改密码
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</view>
<view class="nav" data-path="authentication">
<iconfont class="icon" type="shimingrenzheng" size="21" />实名认证
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</view>
<view class="nav gap" data-path="pro_authentication">
<iconfont class="icon" type="wode-zhiyerenzheng" size="21" />职业认证
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</view>
<button open-type="feedback" class="nav" style="width:auto">
<iconfont class="icon" type="fankui" size="21" />小程序反馈
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</button>
<button open-type="contact" class="nav" style="width:auto">
<iconfont class="icon" type="kefu" size="21" />小程序客服
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</button>
<navigator url="/account/pages/about/about" class="nav about gap">
<iconfont class="icon" type="guanyu" size="21" />关于
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</navigator>
<navigator class="nav" url="/account/pages/accounts/accounts">
<iconfont class="icon" size="21" type="qiehuanzhanghao" />切换账号
<iconfont type="jinru" color="dimgrey" size="15" class="enter"></iconfont>
</navigator>
</view>
<view>
<button class="login" type="main" wx:if="{{!user.id||user.id==2}}" bindtap="enter_login">登录</button>
<button class="logout" wx:elif="{{user.id!=2}}" bindtap="logout">退出登录</button>
<button class="login logout" wx:elif="{{user.id!=2}}" bindtap="logout">退出登录</button>
</view>
<view class="version">
<text catchtap="onTapVersion">当前版本:{{version}}</text>
</view>
<join-course-modal hidden="{{!showModal}}" />

@ -1,29 +1,49 @@
.auth-tip{
margin-right: 12px;
}
.nav-list{
margin-top: 4px;
}
.gap{
margin-bottom: 4px;
}
.nav {
font-size: 16px;
background: white;
border-bottom: 1px solid #eee;
padding: 0 14px;
height: 42px;
line-height: 42px;
text-align: left;
font-weight: normal;
display: flex;
align-items: center;
position: relative;
}
.nav>.enter{
position: absolute;
right: 12px;
}
.nav>.icon{
margin-right: 10px;
}
button.nav::after{
border: none;
}
.login{
margin: 16rpx 70rpx;
margin-top: 24rpx;
}
.logout{
background: red;
color: white;
margin-top: 16rpx;
background-color: #fa5151;
}
.version{
font-size: 11px;
color: grey;
text-align: center;
margin-top: 20px;
margin-bottom: 8px;
}
.user-display{

@ -11,6 +11,7 @@ const categories = [{ text: "我学习的", value: "study" }, { text: "我管理
Component({
data: {
imgDir: global.config.imgDir,
attachDir:global.config.attachDir,
categories,
statuses: [{ text: "正在进行", value: "processing" }, { text: "已结束", value: "end" }],
courses: [],
@ -44,10 +45,22 @@ Component({
this.options["status"] = value.value;
this.pullCourses({refresh:1});
},
show_join_course_modal: function (event) {
this.setData({ show_join_course_modal: true });
addCourse(){
if(app.user().user_identity=="学生"){
this.setData({showModal:1});
}else{
wx.showActionSheet({
itemList: ["加入课堂",'创建课堂'],
success:res=>{
if(res.tapIndex==0){
this.setData({ showModal: 1 });
}else{
app.navigateTo({ url:"{course_setting}?intent=create"});
}
}
})
}
},
enter_course: function (event) {
console.log(event);
let { id, course_name } = event.currentTarget.dataset;
@ -79,7 +92,7 @@ Component({
courses = courses.filter(i => {
return i.is_end == (data.status == "end")
});
console.log(courses);
//console.log(courses);
if(!refresh)
courses = this.data.courses.concat(courses);
this.setData({ courses });

@ -14,6 +14,6 @@
</view>
</scroll-view>
<!-- {{imgDir}}add.png -->
<image class="add-course" src="{{imgDir}}add.png" bindtap="show_join_course_modal"></image>
<join-course-modal hidden="{{!show_join_course_modal}}"/>
<image class="add-course" src="{{attachDir}}751591" bindtap="addCourse"></image>
<join-course-modal hidden="{{!showModal}}"/>
</view>

@ -2,7 +2,6 @@
<navigation-bar title="{{shixun.name}}"/>
</page-meta>
<wxs src="./shixun.wxs" module="handler"/>
<require-login bg="#0080f0" user_id="{{user.user_id}}"/>
<view class="header">
<view class="shixun-title">{{shixun.name}}</view>
<view class="shixun-detail">
@ -20,6 +19,7 @@
</view>
</view>
</view>
<require-login bg="#00b0f0" message="点击登陆,可以获取更多内容哦"/>
<nav-bar list="{{list}}" current="{{current}}" type="line" bindchange="switchNav"/>
<swiper class="body" current="{{current}}" bindchange="switchNav" circular="1">
<swiper-item>

@ -9,13 +9,18 @@ Page({
this.setData({homework_id});
this.refresh();
},
async refresh(){
refresh(){
let {homework_id} = this.data;
let data = await app.api("homework_commons.works_list")({homework_id});
this.setData(data);
app.api("homework_commons.works_list")({homework_id})
.then(res=>{
this.setData(res);
})
.catch(e=>{
app.showEror(e);
})
},
enterShixun(){
app.navigateTo({url:`{shixun}?identifier=${this.data.shixun_identifier}`});
app.redirectTo({url:`{shixun}?identifier=${this.data.shixun_identifier}`});
},
onPullDownRefresh: function () {

@ -1,7 +1,17 @@
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
"rules": [
{
"action": "allow",
"page": "shixun/pages/shixun/shixun",
"params": [
"identifier"
],
"matching": "inclusive"
},
{
"action": "allow",
"page": "*"
}
]
}

@ -17,8 +17,13 @@ Component({
methods: {
analyse(){
//console.log(this.data);
var outputs = this.data.data.output.split(/\n/).map(i=>({text:i}));
var actual_outputs = this.data.data.actual_output.split(/\n/).map(i=>({text:i}));
let {output="",actual_output=""} = this.data.data;
//console.log(this.data,actual_output,output);
output = output||"";
actual_output = actual_output||"";
console.log(this.data, actual_output, output);
var outputs = output.split(/\n/).map(i=>({text:i}));
var actual_outputs = actual_output.split(/\n/).map(i=>({text:i}));
var lines = Math.min(outputs.length, actual_outputs.length);
for(var i=0;i<lines;i++){
if(outputs[i].text!=actual_outputs[i].text){

@ -66,6 +66,7 @@
"id": -1,
"name": "account/pages/profile/profile",
"pathName": "account/pages/profile/profile",
"query": "",
"scene": null
},
{
@ -74,6 +75,41 @@
"pathName": "account/pages/profile/school_select/school_select",
"query": "keyword=国",
"scene": null
},
{
"id": 2,
"name": "home",
"pathName": "pages/home/home",
"query": "name=sasasasas",
"scene": null
},
{
"id": 3,
"name": "dev/pages/dev/dev",
"pathName": "dev/pages/dev/dev",
"query": "",
"scene": null
},
{
"id": -1,
"name": "authentication",
"pathName": "account/pages/authentication/authentication",
"query": "",
"scene": null
},
{
"id": -1,
"name": "account/pages/pro_authentication/pro_authentication",
"pathName": "account/pages/pro_authentication/pro_authentication",
"query": "",
"scene": null
},
{
"id": -1,
"name": "course/pages/course_invite/course_invite",
"pathName": "course/pages/course_invite/course_invite",
"query": "",
"scene": null
}
]
}

Loading…
Cancel
Save