拆分复杂界面为多个组件,修补头像上传bug

master
educoder_weapp 5 years ago
parent 65d57faed8
commit c4f55879d4

@ -24,8 +24,7 @@ Page({
data: 1, data: 1,
}) })
}, },
login: function () { login: function ({login, password}) {
const { login, password } = this.data;
app.callApi({ app.callApi({
name: "accounts.login", data: { login: login, password: password, autologin: 1 }, name: "accounts.login", data: { login: login, password: password, autologin: 1 },
success: res => { success: res => {

@ -44,7 +44,7 @@ Page({
encoding: "base64", encoding: "base64",
success: res => { success: res => {
let image = "data:image/jpeg;base64," + res.data; let image = "data:image/jpeg;base64," + res.data;
app.api("accounts.avatar")({image}).then(resolve); app.api("users.accounts.avatar")({image}).then(resolve);
}, },
fail:reject fail:reject
}); });

@ -1,4 +1,4 @@
<import src="/we-cropper/dist/we-cropper.wxml"/> <import src="/avatar/we-cropper/dist/we-cropper.wxml"/>
<view class="cropper-wrapper"> <view class="cropper-wrapper">
<template is="we-cropper" data="{{...cropperOpt}}" /> <template is="we-cropper" data="{{...cropperOpt}}" />
<view class="operation flex-wrap"> <view class="operation flex-wrap">

@ -1,6 +1,7 @@
Component({ Component({
properties: { properties: {
data:Object, //@todo: simplify
course_id:Number, course_id:Number,
teacher:Object, teacher:Object,
name:String, name:String,

@ -14,6 +14,7 @@ view.common{
} }
view.c-nav { view.c-nav {
box-sizing: border-box; box-sizing: border-box;
border-bottom: 2px solid transparent;
transition: all 0.26s ease; transition: all 0.26s ease;
} }
view.c-nav.active{ view.c-nav.active{
@ -21,6 +22,9 @@ view.c-nav.active{
font-size: 15px; font-size: 15px;
border-bottom: 2px solid #0080f0; border-bottom: 2px solid #0080f0;
} }
view.c-plain{
transition: all 0.26s ease;
}
view.c-plain.active{ view.c-plain.active{
color: #0080f0; color: #0080f0;
font-size: 15px; font-size: 15px;
@ -50,7 +54,7 @@ text.c-line.active{
text.c-line::after{ text.c-line::after{
transition: all 0.26s ease; transition: all 0.26s ease;
width: 0px; width: 0px;
height: 5px; height: 3.2px;
position: absolute; position: absolute;
content: ""; content: "";
bottom: 0; bottom: 0;
@ -58,5 +62,5 @@ text.c-line::after{
} }
text.c-line.active::after{ text.c-line.active::after{
width: 22px; width: 22px;
background: #0080f0; background: #00a0f0;
} }

@ -0,0 +1,35 @@
if (!global.towxml)
global.towxml = require('../../towxml/index');
Component({
properties: {
nodes:{
type:Object,
optionalTypes:[String],
observer:function(nodes){
if(typeof nodes=="string")
this.process(nodes);
}
},
base:{
type:String,
value: "https://www.educoder.net/"
}
},
data: {
isRich:0
},
methods: {
process(nodes){
if(!nodes.match(/^\s*?<.+>.*<\/.+>\s *? $ /)){
nodes = nodes.replace(/(#+)/g, "$1 ").replace(/`$$(.*)$$`/g, "\$$1\$").replace(/`\$\$(.*)\$\$`/g, "\$$1\$");
nodes = global.towxml(nodes, "markdown", {base:this.data.base});
this.setData({nodes});
}else{
this.setData({isRich:true})
}
}
}
})

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"towxml":"/towxml/towxml"
}
}

@ -0,0 +1,2 @@
<rich-text wx:if="{{isRich}}" nodes="{{nodes}}"/>
<toxwml wx:else modes="{{nodes}}"/>

@ -0,0 +1,15 @@
Component({
properties: {
data:Object
},
data: {
},
methods: {
}
})

@ -0,0 +1,5 @@
<nav-bar list="{{navList}}" bindchange="switchNav"></nav-bar>
<scroll-view refresher-enabled="1" bindrefresherrefresh="onPullDownRefresh">
</scroll-view>

@ -0,0 +1 @@
/* course/components/common-homework-item/common-homework-item.wxss */

@ -0,0 +1,22 @@
const app = getApp();
Component({
properties: {
course_id:Number,
refresh:{
type:Number,
observer:function(r){
if (r) {
this.onPullDownRefresh();
this.setData({ refresh: false });
}
}
}
},
data: {
},
methods: {
}
})

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

@ -0,0 +1,2 @@
<!--course/components/common-homework/common-homework.wxml-->
<text>course/components/common-homework/common-homework.wxml</text>

@ -0,0 +1 @@
/* course/components/common-homework/common-homework.wxss */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 733 B

@ -0,0 +1,38 @@
const app = getApp();
Component({
properties: {
data:Object
},
data: {
},
methods: {
answer_choice_question: function ({ detail: { value }, currentTarget: { dataset } }) {
console.log("answer_question");
console.log(value);
console.log(dataset);
let exercise_choice_id;
if (Array.isArray(value)) {
exercise_choice_id = [];
for (var i of value) {
exercise_choice_id.push(parseInt(i));
}
console.log(exercise_choice_id);
} else {
exercise_choice_id = parseInt(value);
console.log(exercise_choice_id);
}
app.api("exercise_questions.exercise_answers")({ question_id: dataset.question_id, exercise_choice_id })
.then(res => { console.log("answer_question"); console.log(res); })
.catch(error => {
console.error(error);
wx.showToast({
title: error.toString(),
icon: "none"
})
});
},
}
})

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"rich-md": "/components/rich-md/rich-md"
}
}

@ -0,0 +1,28 @@
<view class="question">
<text class="hint">第{{question.q_position}}题</text>
<rich-text class="question-title" nodes="{{question.question_title}}" space="nbsp"></rich-text>
<view wx:if="{{question.question_type==0 || question.question_type==2}}">
<radio-group class="choices" bindchange="answer_choice_question" data-question_id="{{question.question_id}}">
<block wx:for="{{question.question_choices}}" wx:for-item="choice" wx:key="choice_id">
<radio disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="choice" checked="{{choice.user_answer_boolean}}" value="{{choice.choice_id}}">
<view class="choice">
<text class="choice-text">{{choice.choice_text}}</text>
<text wx:if="{{choice.standard_boolean}}" class="error standard-choice">正确答案</text>
</view>
</radio>
</block>
</radio-group>
</view>
<view wx:elif="{{question.question_type==1}}">
<checkbox-group class="choices" bindchange="answer_choice_question" data-question_id="{{question.question_id}}">
<block wx:for="{{question.question_choices}}" wx:for-item="choice" wx:key="choice_id">
<checkbox class="choice" disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" checked="{{choice.user_answer_boolean}}" value="{{choice.choice_id}}">
<view class="choice">
<text class="choice-text">{{choice.choice_text}}</text>
<text wx:if="{{choice.standard_boolean}}" class="error standard-choice">正确答案</text>
</view>
</checkbox>
</block>
</checkbox-group>
</view>
</view>

@ -0,0 +1,50 @@
.question{
background: white;
margin: 20rpx -6rpx;
padding: 4rpx 20rpx 22rpx 22rpx;
border-radius: 18rpx;
}
.question-title{
display: inline-block;
margin: 5rpx 0rpx 12rpx 0rpx;
}
.choices{
display: flex;
flex-direction: column;
}
checkbox.choice{
margin-bottom: 12rpx;
}
view.choice{
width: 600rpx;
}
.main-input{
height: 120rpx;
margin: 18rpx 0 4rpx 18rpx;
border: 1rpx solid lightgray;
border-radius: 12rpx;
padding: 12rpx 10rpx;
}
view.null-input{
align-items: center;
}
input.null-input{
border: 1rpx solid lightgray;
padding: 12rpx 6rpx;
margin: 6rpx 10rpx;
border-radius: 10rpx;
}
.standard-choice{
margin-left: 24rpx;
}
standard-null-input{
align-items: center;
}

@ -0,0 +1,23 @@
// exercise/components/main-question/main-question.js
Component({
properties: {
},
data: {
},
methods: {
answer_main_question: function ({ detail: { value }, currentTarget: { dataset } }) {
console.log("answer_main_question");
console.log(value);
console.log(dataset);
app.api("exercise_questions.exercise_answers")({ question_id: dataset.question_id, answer_text: value })
.then(res => { console.log("answer_main_question"); console.log(res); })
.catch(e => {
console.error(e);
app.showError(e);
});
},
}
})

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

@ -0,0 +1,12 @@
<view>
<textarea disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="main-input"
placeholder="输入答案"
bindblur="answer_main_question"
value="{{question.user_answer[0]||''}}"
data-question_id="{{question.question_id}}">
</textarea>
<view wx:if="{{question.standard_answer}}" class="standard-main-input">
<text class="hint">参考答案:</text>
<text class="error">{{question.standard_answer[0]||'暂无'}}</text>
</view>
</view>

@ -0,0 +1 @@
/* exercise/components/main-question/main-question.wxss */

@ -0,0 +1,25 @@
const app = getApp();
Component({
properties: {
},
data: {
},
methods: {
answer_null_question: function ({ detail: { value }, currentTarget: { dataset } }) {
console.log("answer_main_question");
console.log(value);
console.log(dataset);
app.api("exercise_questions.exercise_answers")({ question_id: dataset.question_id, exercise_choice_id: dataset.exercise_choice_id, answer_text: value })
.then(res => { console.log("answer_main_question"); console.log(res); })
.catch(error => {
console.error(error);
wx.showToast({
title: error.toString(),
icon: "none"
})
});
},
}
})

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

@ -0,0 +1,20 @@
<view>
<block wx:for="{{question.null_inputs}}" wx:for-item="null_input">
<view class="null-input flex-wrap">
<text class="hint">填空{{null_input.choice_id}}</text>
<input disabled="{{exercise.user_exercise_status==1 || exercise.user_exercise_status==4}}" class="null-input"
placeholder="输入填空{{null_input.choice_id}}答案"
data-question_id="{{question.question_id}}"
data-exercise_choice_id="{{null_input.choice_id}}"
value="{{null_input.answer_text}}"
bindblur="answer_null_question">
</input>
</view>
</block>
<view wx:if="{{question.standard_answer}}" class="standard-null-inputs">
<view class="standard-null-input flex-wrap" wx:for="{{question.standard_answer}}" wx:for-item="answer">
<text class="hint">第{{answer.choice_id}}空答案:</text>
<text class="error" style="padding-top: 12rpx;">{{answer.answer_text}}</text>
</view>
</view>
</view>

@ -0,0 +1 @@
/* exercise/components/null-question/null-question.wxss */

@ -18,7 +18,6 @@ Page({
title: '请登陆后重试', title: '请登陆后重试',
icon: "none" icon: "none"
}) })
//console.log("require_login");
return; return;
} }
let questions = res.exercise_questions; let questions = res.exercise_questions;
@ -140,64 +139,29 @@ Page({
} }
}) })
}, },
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) { onLoad: function (options) {
this.exercise_id = options.exercise_id; this.exercise_id = options.exercise_id;
this.course_name = options.exercise_name;//todo finish this.course_name = options.exercise_name;//todo finish
}, },
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () { onShow: function () {
if(this.data.loading){ if(this.data.loading){
this.pull_questions(); this.pull_questions();
} }
}, },
onError: function(e){
console.error(e);
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () { onHide: function () {
this.save_exercise({show_loading: false}); this.save_exercise({show_loading: false});
}, },
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () { onUnload: function () {
this.save_exercise({ show_loading: false }); this.save_exercise({ show_loading: false });
}, },
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () { onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
}, },
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () { onShareAppMessage: function () {
} }

@ -1,3 +1,7 @@
{ {
"usingComponents": {} "usingComponents": {
"choice-question":"/exercise/components/choice-question/choice-question",
"main-question": "/exercise/components/main-question/main-question",
"null-question": "/exercise/components/null-question/null-question"
}
} }

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

@ -11,62 +11,11 @@
width: 50%; width: 50%;
} }
.save{ .save{
background-color: #4797f8; background-color: #00b0f0;
} }
.commit{ .commit{
background-color: orangered; background-color: orangered;
} }
.container{ .container{
padding-bottom: 40px; padding-bottom: 40px;
} }
.question{
background: white;
margin: 20rpx -6rpx;
padding: 4rpx 20rpx 22rpx 22rpx;
border-radius: 18rpx;
}
.question-title{
display: inline-block;
margin: 5rpx 0rpx 12rpx 0rpx;
}
.choices{
display: flex;
flex-direction: column;
}
checkbox.choice{
margin-bottom: 12rpx;
}
view.choice{
width: 600rpx;
}
.main-input{
height: 120rpx;
margin: 18rpx 0 4rpx 18rpx;
border: 1rpx solid lightgray;
border-radius: 12rpx;
padding: 12rpx 10rpx;
}
view.null-input{
align-items: center;
}
input.null-input{
border: 1rpx solid lightgray;
padding: 12rpx 6rpx;
margin: 6rpx 10rpx;
border-radius: 10rpx;
}
.standard-choice{
margin-left: 24rpx;
}
standard-null-input{
align-items: center;
}

@ -38,7 +38,7 @@ export default class Client{
this.on("before","users.homepage_info", getLogin); this.on("before","users.homepage_info", getLogin);
this.on("before","homepage_info", getLogin) this.on("before","homepage_info", getLogin)
this.on("before","unread_message_info", getLogin); this.on("before","unread_message_info", getLogin);
this.on("before","accounts.avatar",getLogin); this.on("before","users.accounts.avatar",getLogin);
this.on("success", "accounts.logout", res=>{ this.on("success", "accounts.logout", res=>{
this.synch = 0; this.synch = 0;
wx.setStorageSync("autologin", 0); wx.setStorageSync("autologin", 0);
@ -87,9 +87,9 @@ export default class Client{
} }
return {randomcode:this.randomcode,client_key:this.client_key}; return {randomcode:this.randomcode,client_key:this.client_key};
} }
api(name,config={}){ api(name,config={},data={}){
return data=>{ return ({success, fail, complete,..._data}={})=>{
return this.callApi({name,config, data}); return this.callApi({name,config, data:{...data,..._data}, success, fail, complete});
} }
} }
callApi({ name, data={},config={}, success, fail, complete}) { callApi({ name, data={},config={}, success, fail, complete}) {

@ -49,7 +49,10 @@ Page({
.then(res=>{ .then(res=>{
console.log(res); console.log(res);
this.setData({courses: res.courses||[]}); this.setData({courses: res.courses||[]});
}).catch(console.error); }).catch(e=>{
this.setData({courses:[]});
console.error
});
console.log(this.data); console.log(this.data);
}, },
onLoad: function (options) { onLoad: function (options) {

@ -1,7 +1,7 @@
<require-login user_id="{{user.user_id}}"/> <require-login user_id="{{user.user_id}}"/>
<nav-bar list="{{categories}}" current="{{current_cate}}" bindchange="onCategoryChange"/> <nav-bar list="{{categories}}" current="{{current_cate}}" bindchange="onCategoryChange"/>
<view class="nav-wrap"> <view class="nav-wrap">
<nav-bar list="{{statuses}}" width="300" itemWidth="0" mg="20" cancellable="1" current="-1" type="plain" bg='' bindchange="onStatusChange"/> <nav-bar list="{{statuses}}" width="300" itemWidth="140" cancellable="1" current="-1" type="plain" bg='' bindchange="onStatusChange"/>
</view> </view>
<scroll-view scroll-y="1" refresher-enabled="1" bindrefresherrefresh="onPullDownRefresh" class="body"> <scroll-view scroll-y="1" refresher-enabled="1" bindrefresherrefresh="onPullDownRefresh" class="body">
<view class="container"> <view class="container">

Loading…
Cancel
Save