瀏覽代碼

fix(fronnt): 交互修复

Go 4 年之前
父節點
當前提交
c806cd1971

+ 1 - 0
front/project/Constant.js

@@ -152,6 +152,7 @@ export const FaqChannel = [
   { label: 'GetReady', value: 'getready' },
   { label: '练习', value: 'exercise' },
   { label: '预习作业', value: 'preview', parent: 'exercise' },
+  { label: '长难句', value: 'sentence', parent: 'exercise' },
   { label: '模考', value: 'examination' },
   { label: 'CAT难度适应性', value: 'cat', parent: 'examination' },
   { label: '非CAT', value: 'base', parent: 'examination' },

+ 17 - 13
front/project/admin/routes/setting/index/page.js

@@ -12,16 +12,16 @@ export default class extends Page {
   initData() {
     System.getIndex().then(result => {
       const { form } = this.props;
-      (result.course || []).forEach((row, index) => {
-        form.getFieldDecorator(`index.course.${index}.image`);
-      });
-      (result.activity || []).forEach((row, index) => {
-        form.getFieldDecorator(`index.activity.${index}.image`);
-      });
-      (result.course || []).forEach((row, index) => {
-        form.getFieldDecorator(`index.evaluation.${index}.avatar`);
-      });
-      form.setFieldsValue(flattenObject(result, 'index', true));
+      // (result.course || []).forEach((row, index) => {
+      //   form.getFieldDecorator(`index.course.${index}.image`);
+      // });
+      // (result.activity || []).forEach((row, index) => {
+      //   form.getFieldDecorator(`index.activity.${index}.image`);
+      // });
+      // (result.course || []).forEach((row, index) => {
+      //   form.getFieldDecorator(`index.evaluation.${index}.avatar`);
+      // });
+      form.setFieldsValue(flattenObject(result, 'index'));
       this.setState({ load: true, indexInfo: result });
     });
     System.getBase().then(result => {
@@ -58,9 +58,9 @@ export default class extends Page {
       if (!err) {
         // const { indexInfo } = this.state;
         const { index } = form.getFieldsValue();
-        index.course = Object.keys(index.course || {}).map((key) => index.course[key]);
-        index.activity = Object.keys(index.activity || {}).map((key) => index.activity[key]);
-        index.evaluation = Object.keys(index.evaluation || {}).map((key) => index.evaluation[key]);
+        index.course = index.course.filter(row => row);
+        index.activity = index.activity.filter(row => row);
+        index.evaluation = index.evaluation.filter(row => row);
         System.setIndex(index)
           .then(() => {
             this.setState({ indexInfo: index });
@@ -221,6 +221,7 @@ export default class extends Page {
                   rules: [
                     { required: true, message: '上传图片' },
                   ],
+                  initialValue: row.image,
                 })(
                   <Upload
                     listType="picture-card"
@@ -282,6 +283,7 @@ export default class extends Page {
                   rules: [
                     { required: true, message: '上传图片' },
                   ],
+                  initialValue: row.image,
                 })(
                   <Upload
                     listType="picture-card"
@@ -322,6 +324,7 @@ export default class extends Page {
         <Row>
           {evaluation.map((row, index) => {
             const avatar = getFieldValue(`index.evaluation.${index}.avatar`) || null;
+            console.log(getFieldValue(`index.evaluation.${index}.avatar`));
             return <Col span={7} offset={index % 3 ? 1 : 0}><Card>
               <Button className="delete-button" size="small" onClick={() => {
                 this.deleteLength('evaluation', index, 1);
@@ -353,6 +356,7 @@ export default class extends Page {
                   rules: [
                     { required: true, message: '上传图片' },
                   ],
+                  initialValue: row.avatar,
                 })(
                   <Upload
                     listType="picture-card"

+ 1 - 0
front/project/admin/routes/subject/question/page.js

@@ -87,6 +87,7 @@ export default class extends Page {
             form.getFieldDecorator(`content.questions[${index}].direction`);
             form.getFieldDecorator(`content.questions[${index}].first`);
             form.getFieldDecorator(`content.questions[${index}].second`);
+            form.getFieldDecorator(`content.questions[${index}].description`);
             if (type === 'double') {
               form.getFieldDecorator(`answer.questions[${index}].${type}[${this.uuid[index]}][0]`);
               form.getFieldDecorator(`answer.questions[${index}].${type}[${this.uuid[index]}][1]`);

+ 5 - 2
front/project/h5/routes/page/bind/page.js

@@ -25,7 +25,7 @@ export default class extends Page {
     data = data || {};
     empty = empty || {};
     data[field] = value;
-    empty[field] = !value;
+    if (value) empty[field] = !value;
     this.setState({ data, empty });
   }
 
@@ -95,7 +95,10 @@ export default class extends Page {
     const { data, needEmail, mobileError, emailError, validError } = this.state;
     const { area, mobile, mobileVerifyCode, email } = data;
     if (mobileError || emailError || validError) return;
-    if (!area || !mobile || !mobileVerifyCode) return;
+    if (!area || !mobile || !mobileVerifyCode || (needEmail && !email)) {
+      this.setState({ error: { mobile: !mobile, mobileVerifyCode: !mobileVerifyCode, email: !email } });
+      return;
+    }
     if (needEmail && !email) return;
     User.bind(area, mobile, mobileVerifyCode, email)
       .then(() => {

+ 13 - 0
front/project/www/components/Examination/index.js

@@ -56,6 +56,19 @@ export default class extends Component {
       this.init = true;
       My.getPrepare()
         .then(result => {
+          result.stat = result.stat || {};
+          if (!result.stat.status) {
+            result.stat.status = [];
+          }
+          if (!result.stat.goal) {
+            result.stat.goal = [];
+          }
+          if (!result.stat.examinationTime) {
+            result.stat.examinationTime = [];
+          }
+          if (!result.stat.scoreTime) {
+            result.stat.scoreTime = [];
+          }
           const statusTotal = result.stat.status.reduce((p, n) => { return p + n.value; }, 0);
           const goalTotal = result.stat.goal.reduce((p, n) => { return p + n.value; }, 0);
           const examinationTimeTotal = result.stat.examinationTime.reduce((p, n) => { return p + n.value; }, 0);

+ 1 - 1
front/project/www/components/Header/index.js

@@ -90,7 +90,7 @@ function Header(props) {
             >
               <Link to="/my/main" className="info">
                 <Assets className="avatar" name="sun_blue" src={user.info.avatar} />
-                <span className="t-2 f-s-12">{user.info.nickname || `qx${user.info.mobile}`}</span>
+                <span className="t-2 f-s-12">{(user.info.nickname || '').substr(0, 5) || `qx${user.info.mobile}`}</span>
               </Link>
             </Dropdown>
           ) : (<Button onClick={() => {

+ 26 - 24
front/project/www/components/Login/index.js

@@ -21,7 +21,7 @@ export default class Login extends Component {
   constructor(props) {
     super(props);
     this.validNumber = 0;
-    this.state = { type: LOGIN_WX, empty: {}, error: {}, data: { area: MobileArea[0].value } };
+    this.state = { type: LOGIN_WX, empty: {}, data: { area: MobileArea[0].value } };
     this.validMobileNumber = 0;
     this.validEmailNumber = 0;
     window.addEventListener(
@@ -57,22 +57,22 @@ export default class Login extends Component {
   }
 
   login() {
-    const { data, needEmail, mobileError, validError, emailError, error } = this.state;
+    const { data, needEmail, mobileError, validError, emailError, empty } = this.state;
     const { area, mobile, mobileVerifyCode, email } = data;
     if (mobileError || emailError || validError) return;
     if (!area || !mobile || !mobileVerifyCode || (needEmail && !email)) {
-      error[LOGIN_PHONE] = { mobile: !mobile, mobileVerifyCode: !mobileVerifyCode, email: !email };
-      this.setState({ error });
+      empty[LOGIN_PHONE] = { mobile: !mobile, mobileVerifyCode: !mobileVerifyCode, email: !email };
+      this.setState({ empty });
       return;
     }
-    error[LOGIN_PHONE] = {};
-    this.setState({ error });
+    empty[LOGIN_PHONE] = {};
+    this.setState({ empty });
     User.login(area, mobile, mobileVerifyCode, email, null, false)
       .then(result => {
         if (result.bindWechat) {
           this.close();
         } else {
-          this.setState({ type: BIND_WX });
+          this.changeType(BIND_WX);
         }
       })
       .catch(err => {
@@ -118,11 +118,11 @@ export default class Login extends Component {
         if (result.bindMobile) {
           this.close();
         } else {
-          this.setState({ type: BIND_PHONE });
+          this.changeType(BIND_PHONE);
         }
       })
       .catch(err => {
-        this.setState({ type: BIND_WX_ERROR, wechatError: err.message });
+        asyncSMessage(err.message, 'error');
       });
   }
 
@@ -131,8 +131,8 @@ export default class Login extends Component {
       .then(() => {
         this.close();
       })
-      .catch(err => {
-        this.setState({ type: BIND_WX_ERROR, wechatError: err.message });
+      .catch(() => {
+        this.changeType(BIND_WX_ERROR);
       });
   }
 
@@ -141,7 +141,7 @@ export default class Login extends Component {
     data = data || {};
     empty = empty || {};
     data[field] = value;
-    empty[field] = !value;
+    if (value) empty[this.state.type][field] = !value;
     this.setState({ data, empty });
   }
 
@@ -207,6 +207,10 @@ export default class Login extends Component {
       });
   }
 
+  changeType(type) {
+    this.setState({ type, empty: {}, mobileError: '', emailError: '', validError: '' });
+  }
+
   render() {
     const { type } = this.state;
     const { user } = this.props;
@@ -229,6 +233,7 @@ export default class Login extends Component {
               // 绑定微信错误,返回重新绑定微信
               this.setState({ type: BIND_WX });
             } else {
+              this.setState({ type: LOGIN_WX });
               User.closeLogin(new Error('no login'));
             }
           }}
@@ -254,8 +259,8 @@ export default class Login extends Component {
   }
 
   renderLoginPhone() {
-    const { needEmail, registerContract = {}, privacyContract, error = {} } = this.state;
-    const emptyError = error[LOGIN_PHONE] || {};
+    const { needEmail, registerContract = {}, privacyContract, empty = {} } = this.state;
+    const emptyError = empty[LOGIN_PHONE] || {};
     return (
       <div className="body">
         <div className="title">手机号登录</div>
@@ -331,7 +336,7 @@ export default class Login extends Component {
           <a
             className="other"
             onClick={() => {
-              this.setState({ type: LOGIN_WX });
+              this.changeType(LOGIN_WX);
             }}
           >
             <Assets name="code" />
@@ -358,7 +363,7 @@ export default class Login extends Component {
           <a
             className="other"
             onClick={() => {
-              this.setState({ type: LOGIN_PHONE });
+              this.changeType(LOGIN_PHONE);
             }}
           >
             <Assets name="phone" />
@@ -369,8 +374,8 @@ export default class Login extends Component {
   }
 
   renderBindPhone() {
-    const { needEmail = true, registerContract = {}, privacyContract = {}, error = {} } = this.state;
-    const emptyError = error[BIND_PHONE] || {};
+    const { needEmail, registerContract = {}, privacyContract = {}, empty = {} } = this.state;
+    const emptyError = empty[BIND_PHONE] || {};
     return (
       <div className="body">
         <div className="title">绑定手机号</div>
@@ -429,15 +434,12 @@ export default class Login extends Component {
             <a href={`/contract/${privacyContract.key}`} target="_blank">
               《{privacyContract.title}》
             </a>
-            <a className="f-r" onClick={() => this.setState({ type: LOGIN_PHONE })}>
-              使用手机号码登录
-            </a>
           </div>
         )}
-        {!needEmail && (
+        {this.state.mobileError && (
           <div className="m-b-2">
-            <a className="f-r" onClick={() => this.setState({ type: LOGIN_PHONE })}>
+            <a className="f-r" onClick={() => this.changeType(LOGIN_PHONE)}>
               使用手机号码登录
             </a>
           </div>
@@ -495,7 +497,7 @@ export default class Login extends Component {
           <GButton
             radius
             onClick={() => {
-              this.setState({ type: LOGIN_WX });
+              this.changeType(LOGIN_WX);
             }}
           >
             扫码登入

+ 19 - 1
front/project/www/components/Other/index.js

@@ -9,6 +9,23 @@ import Tabs from '../Tabs';
 import { User } from '../../stores/user';
 
 export class CommentFalls extends Component {
+  componentDidMount() {
+    this.createLayout();
+  }
+
+  componentWillReceiveProps(nextProps) {
+    if ((nextProps.list || []).length !== (this.props.list || []).length) {
+      this.needUpdate = true;
+    }
+  }
+
+  componentDidUpdate() {
+    if (this.needUpdate) {
+      this.createLayout();
+      this.needUpdate = false;
+    }
+  }
+
   createLayout() {
     const msnry = new Masonry('.comment-falls', {
       itemSelector: '.grid-item',
@@ -18,7 +35,7 @@ export class CommentFalls extends Component {
 
   render() {
     const { list = [] } = this.props;
-    return (
+    return (<div className="comment-falls-wrap">
       <div className="comment-falls">
         {list.map(row => {
           return (
@@ -35,6 +52,7 @@ export class CommentFalls extends Component {
           );
         })}
       </div>
+    </div>
     );
   }
 }

+ 4 - 4
front/project/www/components/Other/index.less

@@ -1,15 +1,15 @@
-.comment-falls {
-  height: 530px;
+.comment-falls-wrap {
+  max-height: 530px;
   overflow-y: auto;
   padding-top: 20px;
   padding-bottom: 20px;
   background: #fff;
 
+  .comment-falls {}
+
   .grid-item {
     width: 25%;
     padding: 5px;
-    float: left;
-    max-height: 260px;
 
     .item {
       max-height: 260px;

+ 34 - 21
front/project/www/components/OtherModal/index.js

@@ -45,7 +45,7 @@ export class BindPhone extends Component {
     if (!props.show || this.props.show) return {};
     const data = Object.assign({}, props.data);
     if (!data.area) data.area = MobileArea[0].value;
-    return { step: props.data.mobile ? 0 : 1, data };
+    return { step: props.data.mobile ? 0 : 1, data, validError: '', empty: {} };
   }
 
   componentWillReceiveProps(nextProps) {
@@ -53,7 +53,7 @@ export class BindPhone extends Component {
   }
 
   onNext() {
-    this.setState({ step: 1 });
+    this.setState({ step: 1, validError: '', mobileError: '', empty: {} });
   }
 
   changeData(field, value) {
@@ -61,18 +61,17 @@ export class BindPhone extends Component {
     data = data || {};
     empty = empty || {};
     data[field] = value;
-    empty[field] = !value;
+    if (value) empty[field] = !value;
     this.setState({ data, empty, mobileError: null });
   }
 
   validMobile() {
     const { data } = this.state;
     const { area, mobile } = data;
-    const { info } = this.props.user;
     if (!area || !mobile) return;
     this.validNumber += 1;
     const number = this.validNumber;
-    if (mobile === info.mobile) {
+    if (mobile === this.props.data.mobile) {
       this.setState({ mobileError: '' });
       return;
     }
@@ -93,7 +92,11 @@ export class BindPhone extends Component {
   sendValid() {
     const { data, mobileError } = this.state;
     const { area, mobile } = data;
-    if (!area || !mobile || mobileError) return Promise.reject();
+    if (mobileError) return Promise.reject();
+    if (!area || !mobile) {
+      this.setState({ empty: { area: !data.area, mobile: !data.mobile } });
+      return Promise.reject();
+    }
     return Common.sendSms(area, mobile)
       .then(result => {
         if (result) {
@@ -111,9 +114,13 @@ export class BindPhone extends Component {
 
   submit() {
     const { data, validError, mobileError } = this.state;
-    if (!data.mobile || !data.area || validError || mobileError) return;
-    const { area, mobile } = data;
-    My.bindMobile(area, mobile)
+    if (validError || mobileError) return;
+    const { area, mobile, mobileVerifyCode } = data;
+    if (!area || !mobile || !mobileVerifyCode) {
+      this.setState({ empty: { area: !data.area, mobile: !data.mobile, mobileVerifyCode: !mobileVerifyCode } });
+      return;
+    }
+    My.bindMobile(area, mobile, mobileVerifyCode)
       .then(() => {
         asyncSMessage('操作成功');
         this.setState({ step: 0, validError: '', mobileError: '' });
@@ -142,7 +149,7 @@ export class BindPhone extends Component {
   renderStep0() {
     const { data } = this.state;
     return (
-      <div className="step-0-layout">
+      <div className="step-0-layout t-2">
         已绑定手机 {data.mobile}
         <a onClick={() => this.onNext()}>修改</a>
       </div>
@@ -223,7 +230,7 @@ export class BindEmail extends Component {
   }
 
   onNext() {
-    this.setState({ step: 1 });
+    this.setState({ step: 1, error: '', empty: {} });
   }
 
   changeData(field, value) {
@@ -231,18 +238,17 @@ export class BindEmail extends Component {
     data = data || {};
     empty = empty || {};
     data[field] = value;
-    empty[field] = !value;
+    if (value) empty[field] = !value;
     this.setState({ data, empty, error: null });
   }
 
   validEmail() {
     const { data } = this.state;
     const { email } = data;
-    const { info } = this.props.user;
     if (!email) return;
     this.validNumber += 1;
     const number = this.validNumber;
-    if (email === info.email) {
+    if (email === this.props.data.email) {
       this.setState({ error: '' });
       return;
     }
@@ -262,7 +268,11 @@ export class BindEmail extends Component {
 
   submit() {
     const { data, error } = this.state;
-    if (!data.email || error) return;
+    if (error) return;
+    if (!data.email) {
+      this.setState({ empty: { email: !data.email } });
+      return;
+    }
     const { email } = data;
     My.bindEmail(email)
       .then(() => {
@@ -289,7 +299,7 @@ export class BindEmail extends Component {
   renderStep0() {
     const { data } = this.state;
     return (
-      <div className="step-0-layout">
+      <div className="step-0-layout t-2">
         已绑定邮箱 {data.email}
         <a onClick={() => this.onNext()}>修改</a>
       </div>
@@ -354,16 +364,19 @@ export class EditInfo extends Component {
     data = data || {};
     empty = empty || {};
     data[field] = value;
-    empty[field] = !value;
-    this.setState({ data, nicknameError: null, empty });
+    if (value) empty[field] = !value;
+    this.setState({ data, empty, nicknameError: null });
   }
 
   submit() {
-    const { data, nicknameError, empty } = this.state;
+    const { data, nicknameError } = this.state;
     if (nicknameError) return;
     if (!data.nickname) {
-      empty.nickname = true;
-      this.setState({ nicknameError: '用户名不能为空!', empty });
+      this.setState({ empty: { nickname: !data.nickname } });
+      return;
+    }
+    if (data.nickname.length < 2 || data.nickname.length > 20) {
+      this.setState({ nicknameError: '用户名长度不足2个自负或超过20个字符' });
       return;
     }
     const { nickname, avatar } = data;

+ 1 - 1
front/project/www/routes/my/course/page.js

@@ -829,7 +829,7 @@ class CourseOnline extends Component {
               <div>
                 <div className="d-i-b m-r-2">
                   <div className="t-2">课时</div>
-                  <div className="t-1 t-s-16">{data.courseNos.length}</div>
+                  <div className="t-1 t-s-16">{(data.courseNos || []).length}</div>
                 </div>
                 <div className="d-i-b">
                   <div className="t-2">总时长</div>

+ 1 - 0
front/project/www/routes/my/main/index.less

@@ -96,6 +96,7 @@
         .g-date {
           right: 0;
           left: unset !important;
+          top: 24px !important;
         }
 
         .cal {

+ 6 - 2
front/project/www/routes/my/main/page.js

@@ -145,6 +145,7 @@ export default class extends Page {
     return {
       day: 'today',
       showExamination: false,
+      showTop: true,
       timeList: [
         { title: '长难句', time: '3h60min', ratio: 10, color: '#3C39CC' },
         { title: '综合推理IR', time: '3h60min', ratio: 10, color: '#9E9CFF' },
@@ -383,7 +384,10 @@ export default class extends Page {
     const { showTop } = this.state;
     return !info.bindPrepare && showTop && <div className="top-layout">
       <Assets name='my_main_banner' onClick={() => this.setState({ showExamination: true })} />
-      <div className='close' onClick={() => this.setState({ showTop: false })} />
+      <div className='close' onClick={(e) => {
+        e.stopPropagation();
+        this.setState({ showTop: false });
+      }} />
       <div className='go' onClick={() => this.setState({ showExamination: true })} />
     </div>;
   }
@@ -532,7 +536,7 @@ export default class extends Page {
                   this.setState({ showEdit: true });
                 }}
               >
-                {info.nickname || `qx${info.mobile}`}{' '}
+                {(info.nickname || '').substr(0, 5) || `qx${info.mobile}`}{' '}
               </div>
               <div className="id">ID: {zeroFill(info.id, 4)} </div>
             </div>

+ 78 - 41
front/project/www/routes/paper/question/detail/index.js

@@ -378,15 +378,31 @@ export default class extends Component {
   }
 
   renderBody() {
-    const { question = { content: {} } } = this.props;
+    const { question = { content: {} }, detail } = this.props;
     const { typeset = 'one' } = question.content;
-    const { hideAnalysis } = this.state;
+    const { hideAnalysis, showAnswer } = this.state;
     const show = typeset === 'one' ? true : !hideAnalysis;
     return (
       <div className="layout-content">
-        <div className="two">
+        <div className={typeset}>
           {this.renderContent()}
-          {question.questionType !== 'awa' && this.renderAnswer()}
+          {typeset === 'two' && (
+            <div className="block">
+              <div className="block-answer">
+                {detail && (
+                  <Switch
+                    checked={showAnswer}
+                    onChange={value => {
+                      this.setState({ showAnswer: value });
+                    }}
+                  >
+                    {showAnswer ? '显示答案' : '关闭答案'}
+                  </Switch>
+                )}
+                {this.renderAnswer()}
+              </div>
+            </div>
+          )}
           {question.questionType === 'awa' && this.renderAWA()}
         </div>
         {question.questionType !== 'awa' && this.renderAnalysis()}
@@ -400,10 +416,11 @@ export default class extends Component {
   }
 
   renderAnalysis() {
-    const { question = { content: {} } } = this.props;
+    const { question = { content: {} }, detail } = this.props;
     const { typeset = 'one' } = question.content;
     const { hideAnalysis, analysisTab } = this.state;
     const show = typeset === 'one' ? true : !hideAnalysis;
+    const { showAnswer } = this.state;
     return (<div className="block">
       <div className={`block-analysis two-analysis ${show ? 'show' : ''}`}>
         <Tabs
@@ -421,7 +438,22 @@ export default class extends Component {
           }}
         />
         <div className="detail">
-          {typeset === 'two' && this.renderAnswer()}
+          {typeset === 'two' && (
+            <div className="block">
+              <div className="block-answer">
+                {detail && <Switch
+                  checked={showAnswer}
+                  onChange={value => {
+                    this.setState({ showAnswer: value });
+                  }}
+                >
+                  {showAnswer ? '显示答案' : '关闭答案'}
+                </Switch>
+                }
+                {this.renderAnswer()}
+              </div>
+            </div>
+          )}
           {this.renderText()}
         </div>
       </div></div>
@@ -447,7 +479,25 @@ export default class extends Component {
           <div className="detail-block">
             <Carousel>
               {associations.map(association => {
-                return <div className="block-text" dangerouslySetInnerHTML={{ __html: this.formatOtherStem(association) }} />;
+                const { questions = [], type } = association.content || {};
+                return <div className="block-text">
+                  <div dangerouslySetInnerHTML={{ __html: this.formatOtherStem(association) }} />
+                  {questions.map((item, index) => {
+                    return (
+                      <div>
+                        <div className="text m-b-2" dangerouslySetInnerHTML={{ __html: item.description }} />
+                        <AnswerList
+                          answer={(question.answer || { questions: [] }).questions[index]}
+                          list={item.select}
+                          type={type}
+                          first={item.first}
+                          second={item.second}
+                          direction={item.direction}
+                        />
+                      </div>
+                    );
+                  })}
+                </div>;
               })}
             </Carousel>
           </div>
@@ -471,41 +521,27 @@ export default class extends Component {
   }
 
   renderAnswer() {
-    const { question = { content: {} }, userQuestion = {}, detail } = this.props;
-    const { questions = [], type, typeset = 'one' } = question.content;
+    const { question = { content: {} }, userQuestion = {} } = this.props;
+    const { questions = [], type } = question.content;
     const { showAnswer } = this.state;
-    return (<div className="block">
-      <div className="block-answer">
-        {detail && typeset === 'two' && (
-          <Switch
-            checked={showAnswer}
-            onChange={value => {
-              this.setState({ showAnswer: value });
-            }}
-          >
-            {showAnswer ? '显示答案' : '关闭答案'}
-          </Switch>
-        )}
-        {questions.map((item, index) => {
-          return (
-            <div>
-              <div className="text m-b-2">{item.description}</div>
-              <AnswerList
-                show={showAnswer}
-                selected={(userQuestion.userAnswer || { questions: [] }).questions[index]}
-                answer={(question.answer || { questions: [] }).questions[index]}
-                distributed={(question.answerDistributed || { questions: [] }).questions[index]}
-                list={item.select}
-                type={type}
-                first={item.first}
-                second={item.second}
-                direction={item.direction}
-              />
-            </div>
-          );
-        })}
-      </div></div>
-    );
+    return questions.map((item, index) => {
+      return (
+        <div>
+          <div className="text m-b-2" dangerouslySetInnerHTML={{ __html: item.description }} />
+          <AnswerList
+            show={showAnswer}
+            selected={(userQuestion.userAnswer || { questions: [] }).questions[index]}
+            answer={(question.answer || { questions: [] }).questions[index]}
+            distributed={(question.answerDistributed || { questions: [] }).questions[index]}
+            list={item.select}
+            type={type}
+            first={item.first}
+            second={item.second}
+            direction={item.direction}
+          />
+        </div>
+      );
+    });
   }
 
   renderContent() {
@@ -538,6 +574,7 @@ export default class extends Component {
           className="text"
           dangerouslySetInnerHTML={{ __html: this.formatStem(steps.length > 0 ? steps[step].stem : question.stem) }}
         />
+        {typeset === 'one' && question.questionType !== 'awa' && this.renderAnswer()}
       </div></div>
     );
   }

+ 2 - 0
front/project/www/routes/paper/question/detail/index.less

@@ -187,6 +187,8 @@
           flex: 1;
           display: flex;
           flex-direction: column;
+          width: 50%;
+          overflow: hidden;
         }
 
         .two {

+ 2 - 2
front/project/www/stores/my.js

@@ -14,8 +14,8 @@ export default class MyStore extends BaseStore {
    * @param {*} area
    * @param {*}
    */
-  bindMobile(area, mobile) {
-    return this.apiPost('/my/mobile', { area, mobile });
+  bindMobile(area, mobile, mobileVerifyCode) {
+    return this.apiPost('/my/mobile', { area, mobile, mobileVerifyCode });
   }
 
   /**

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/controller/api/AuthController.java

@@ -144,7 +144,7 @@ public class AuthController {
             HttpSession session, HttpServletRequest request) {
         User user = (User) shiroHelp.getLoginUser();
         try{
-            if (user == null){
+            if (user == null || user.getId() == null || user.getId()==0){
                 // 直接二维码登录
                 shiroHelp.getSession().login(shiroHelp.oauth(code, "wechat_pc", true));
             }else{

+ 7 - 0
server/gateway-api/src/main/java/com/qxgmat/controller/api/MyController.java

@@ -26,6 +26,7 @@ import com.qxgmat.dto.response.*;
 import com.qxgmat.help.AiHelp;
 import com.qxgmat.help.MailHelp;
 import com.qxgmat.help.ShiroHelp;
+import com.qxgmat.help.SmsHelp;
 import com.qxgmat.service.*;
 import com.qxgmat.service.extend.*;
 import com.qxgmat.service.inline.*;
@@ -57,6 +58,9 @@ import java.util.stream.Collectors;
 @Api(tags = "用户接口", description = "获取与操作当前用户信息", produces = MediaType.APPLICATION_JSON_VALUE)
 public class MyController {
 
+    @Autowired
+    private SmsHelp smsHelp;
+
     @Value("${upload.local_path}")
     private String localPath;
 
@@ -254,6 +258,9 @@ public class MyController {
     @RequestMapping(value = "/mobile", method = RequestMethod.POST)
     @ApiOperation(value = "绑定手机", httpMethod = "POST")
     public Response<Boolean> mobile(@RequestBody @Validated UserMobileDto dto, HttpSession session, HttpServletRequest request) {
+        if (!smsHelp.verifyCode(dto.getArea(), dto.getMobile(), dto.getMobileVerifyCode(), session)) {
+            throw new ParameterException("验证码有误,请重新获取!");
+        }
         User user = (User) shiroHelp.getLoginUser();
         User in = usersService.get(user.getId());
         if (in.getArea().equals(dto.getArea()) && in.getMobile().equals(dto.getMobile())) {

+ 15 - 0
server/gateway-api/src/main/java/com/qxgmat/dto/request/UserMobileDto.java

@@ -17,6 +17,13 @@ public class UserMobileDto {
     @ApiModelProperty(value = "手机号", required = true)
     private String mobile;
 
+    /**
+     * 手机验证码
+     */
+    @NotBlank(message = "手机验证码不能为空!")
+    @ApiModelProperty(value = "手机验证码", required = true)
+    private String mobileVerifyCode;
+
 
     public String getMobile() {
         return mobile;
@@ -33,4 +40,12 @@ public class UserMobileDto {
     public void setArea(String area) {
         this.area = area;
     }
+
+    public String getMobileVerifyCode() {
+        return mobileVerifyCode;
+    }
+
+    public void setMobileVerifyCode(String mobileVerifyCode) {
+        this.mobileVerifyCode = mobileVerifyCode;
+    }
 }