Browse Source

fix(front): 修复restart逻辑

Go 5 years ago
parent
commit
2f6455298e
26 changed files with 157 additions and 149 deletions
  1. 3 0
      front/project/admin/routes/subject/exercise/page.js
  2. 9 7
      front/project/admin/routes/subject/question/page.js
  3. 2 2
      front/project/h5/routes/page/study/page.js
  4. 6 10
      front/project/www/components/Card/index.js
  5. 1 1
      front/project/www/components/Continue/index.js
  6. 1 1
      front/project/www/routes/course/detail/page.js
  7. 4 4
      front/project/www/routes/examination/list/page.js
  8. 1 1
      front/project/www/routes/exercise/list/page.js
  9. 3 3
      front/project/www/routes/exercise/main/page.js
  10. 1 1
      front/project/www/routes/my/course/page.js
  11. 9 6
      front/project/www/routes/my/data/page.js
  12. 7 5
      front/project/www/routes/my/main/page.js
  13. 2 0
      front/project/www/routes/my/message/page.js
  14. 3 4
      front/project/www/routes/page/export/page.js
  15. 2 2
      front/project/www/routes/paper/process/sentence/index.js
  16. 7 7
      front/project/www/routes/paper/question/detail/index.js
  17. 76 75
      front/project/www/routes/paper/report/page.js
  18. 2 2
      front/project/www/routes/preview/list/page.js
  19. 2 2
      front/project/www/routes/textbook/list/page.js
  20. 2 2
      server/data/src/main/java/com/qxgmat/data/relation/mapping/ExaminationPaperRelationMapper.xml
  21. 2 2
      server/data/src/main/java/com/qxgmat/data/relation/mapping/ExercisePaperRelationMapper.xml
  22. 6 6
      server/data/src/main/java/com/qxgmat/data/relation/mapping/PreviewAssignRelationMapper.xml
  23. 2 2
      server/data/src/main/java/com/qxgmat/data/relation/mapping/TextbookPaperRelationMapper.xml
  24. 1 1
      server/gateway-api/src/main/java/com/qxgmat/dto/response/UserReportBaseDto.java
  25. 1 1
      server/gateway-api/src/main/java/com/qxgmat/service/inline/ExercisePaperService.java
  26. 2 2
      server/gateway-api/src/main/java/com/qxgmat/task/AsyncTask.java

+ 3 - 0
front/project/admin/routes/subject/exercise/page.js

@@ -107,6 +107,9 @@ export default class extends Page {
         return QuestionTypeMap[record.question.questionType] || text;
       },
     }, {
+      title: '题目ID',
+      dataIndex: 'title',
+    }, {
       title: '练习册',
       dataIndex: 'paper',
       render: (text) => {

+ 9 - 7
front/project/admin/routes/subject/question/page.js

@@ -131,6 +131,8 @@ export default class extends Page {
       .then((result) => {
         this.refreshPlace(result.questionType);
         this.refreshDifficultScore(result.questionType, result.difficult);
+        form.getFieldDecorator('difficultScore');
+        form.setFieldsValue({ difficultScore: result.difficultScore });
         this.setState({ associationContentQuestionNos: [], realtionQuestionNos: [] });
         if (result.questionNoIds && result.questionNoIds.length > 0) {
           Question.listNo({ ids: result.questionNoIds }).then(list => {
@@ -315,22 +317,22 @@ export default class extends Page {
         let handler;
         data.associationContent = this.state.associationContentQuestionNos.map(row => row.id);
         data.stem = data.stem || '';
-        data.description = (data.stem || '').replace(/<[^>]+>/g, '').replace(/#select#/, '').replace(/#table#/, '');
+        data.description = (data.stem || '').replace(/<[^>]+>/g, '').replace(/#select#/, '').replace(/#table#/, '').replace(/&nbsp;/, '');
         data.qxContent = data.qxContent || '';
         data.officialContent = data.officialContent || '';
 
         data.content = data.content || {};
+        data.answer = data.answer || {};
+        data.answer.questions = (data.answer.questions || []).map((row, index) => {
+          if (row.single) row.single = row.single.filter((r, i) => data.content.questions[index].select[i]);
+          if (row.double) row.double = row.double.filter((r, i) => data.content.questions[index].select[i]);
+          return row;
+        });
         data.content.questions = (data.content.questions || []).map(row => {
           delete row.keys;
           row.select = (row.select || []).filter(r => r);
           return row;
         });
-        data.answer = data.answer || {};
-        data.answer.questions = (data.answer.questions || []).map(row => {
-          if (row.single) row.single = row.single.filter(r => r);
-          if (row.double) row.double = row.double.filter(r => r);
-          return row;
-        });
         data.relationQuestion = this.state.realtionQuestionNos.map(row => row.id);
         if (!data.id) {
           handler = Question.add(data);

+ 2 - 2
front/project/h5/routes/page/study/page.js

@@ -33,14 +33,14 @@ export default class extends Page {
             自{total.createTime && formatDate(total.createTime, 'YYYY-MM-DD')},您已在千行学习<span>{total.days}</span>天
           </div>
           <div className="text">
-            累积<span dangerouslySetInnerHTML={{ __html: formatSeconds(total.time).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span class="s">$1</span>$2') }} />
+            累积<span dangerouslySetInnerHTML={{ __html: formatSeconds(total.time).replace(/([0-9]+)(min|m|hour|h|s)/g, '<span class="s">$1</span>$2') }} />
           </div>
         </div>
         <div className="title">本周数据</div>
         <div className="t-c">
           <div className="item">
             <div className="text">学习时间</div>
-            <div className="value" dangerouslySetInnerHTML={{ __html: formatSeconds(latest.time).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span>$1</span>$2') }} />
+            <div className="value" dangerouslySetInnerHTML={{ __html: formatSeconds(latest.time).replace(/([0-9]+)(min|m|hour|h|s)/g, '<span>$1</span>$2') }} />
           </div>
           <div className="item">
             <div className="text">同比上周</div>

+ 6 - 10
front/project/www/components/Card/index.js

@@ -60,21 +60,21 @@ export default class Card extends Component {
                 <div className="top">
                   <div className="date">{item.time}</div>
                   <div className="action">
-                    {!item.repport.id && (
+                    {!item.report.id && (
                       <IconButton
                         type="start"
                         tip="Start"
                         onClick={() => previewAction && previewAction('start', item)}
                       />
                     )}
-                    {item.repport.id && (
+                    {item.report.id && (
                       <IconButton
                         type="continue"
                         onClick={() => previewAction && previewAction('continue', item)}
                         tip="Continue"
                       />
                     )}
-                    {item.repport.id && (
+                    {item.report.id && (
                       <IconButton
                         type="restart"
                         onClick={() => previewAction && previewAction('restart', item)}
@@ -87,8 +87,7 @@ export default class Card extends Component {
               </div>
             );
           })}
-        </div>
-        )}
+        </div>)}
       </div>
     );
   }
@@ -107,9 +106,7 @@ export default class Card extends Component {
     return (
       <Module
         style={style}
-        className={`card ${!process.payed && !process.startTime ? 'buy' : ''} ${process.payed ? 'open' : ''}  ${
-          process.startTime ? 'ing' : ''
-        }`}
+        className={`card ${!process.payed && !process.startTime ? 'buy' : ''} ${process.payed ? 'open' : ''}  ${process.startTime ? 'ing' : ''}`}
       >
         <div className="header">
           {`${data.titleZh} ${data.titleEn}`}
@@ -243,8 +240,7 @@ export class Card1 extends Component {
               </div>
             );
           })}
-        </div>
-        )}
+        </div>)}
         <div className="bottom">
           有效期: {useStartTime && formatDate(useStartTime, 'YYYY-MM-DD')}至{useEndTime && formatDate(useEndTime, 'YYYY-MM-DD')} <a onClick={() => onPreview && onPreview()}>全部作业></a>
         </div>

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

@@ -23,7 +23,7 @@ function Continue(props) {
               <Assets name="ico_24_continue" svg />
               Continue
             </Button>}
-            {userNumber === questionNumber && <Button radius theme="border" size="small" onClick={() => {
+            {userNumber <= questionNumber && <Button radius theme="border" size="small" onClick={() => {
               onRestart();
             }}>
               <Assets name="ico_24_restart" svg />

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

@@ -72,7 +72,7 @@ export default class extends Page {
                   }}
                 />
               )}
-              {text.report && !!text.report.isFinish && (
+              {text.report && (
                 <IconButton
                   className="m-l-2"
                   type="restart"

+ 4 - 4
front/project/www/routes/examination/list/page.js

@@ -343,13 +343,13 @@ export default class extends Page {
                   }}
                 />
               )}
-              <IconButton
+              {record.report && <IconButton
                 type="restart"
                 tip="Restart"
                 onClick={() => {
                   this.restart(record);
                 }}
-              />
+              />}
             </div>
           );
         },
@@ -506,13 +506,13 @@ export default class extends Page {
                   }}
                 />
               )}
-              <IconButton
+              {record.report && <IconButton
                 type="restart"
                 tip="Restart"
                 onClick={() => {
                   this.restart(record);
                 }}
-              />
+              />}
             </div>
           );
         },

+ 1 - 1
front/project/www/routes/exercise/list/page.js

@@ -96,7 +96,7 @@ export default class extends Page {
             {(record.report && !record.report.isFinish) && <IconButton className="m-r-2" type="continue" tip="Continue" onClick={() => {
               Question.continueLink('exercise', record);
             }} />}
-            {(record.report && record.report.isFinish) && <IconButton type="restart" tip="Restart" onClick={() => {
+            {(record.report) && <IconButton type="restart" tip="Restart" onClick={() => {
               this.restart(record);
             }} />}
           </div>

+ 3 - 3
front/project/www/routes/exercise/main/page.js

@@ -110,9 +110,9 @@ const exerciseColumns = [{
         {(record.report && !record.report.isFinish) && <IconButton className="m-r-2" type="continue" tip="Continue" onClick={() => {
           Question.continueLink('exercise', record);
         }} />}
-        <IconButton type="restart" tip="Restart" onClick={() => {
+        {(record.report) && <IconButton type="restart" tip="Restart" onClick={() => {
           this.restart(record);
-        }} />
+        }} />}
       </div>
     );
   },
@@ -231,7 +231,7 @@ export default class extends Page {
                 }}
               />
             )}
-            {record.report && !!record.report.isFinish && (
+            {record.report && (
               <IconButton
                 type="restart"
                 tip="Restart"

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

@@ -654,7 +654,7 @@ class CourseOnline extends Component {
                   }}
                 />
               )}
-              {text.report && !!text.report.isFinish && (
+              {text.report && (
                 <IconButton
                   className="m-l-2"
                   type="restart"

+ 9 - 6
front/project/www/routes/my/data/page.js

@@ -5,7 +5,7 @@ import Page from '@src/containers/Page';
 import BarChart from '@src/components/BarChart';
 import PieChart from '@src/components/PieChart';
 // import { getMap } from '@src/services/Tools';
-import { getMap, formatPercent, formatSeconds, timeRange } from '@src/services/Tools';
+import { getMap, formatPercent, formatSeconds, formatMinuteSecond, timeRange } from '@src/services/Tools';
 import UserLayout from '../../../layouts/User';
 import UserTable from '../../../components/UserTable';
 import UserAction from '../../../components/UserAction';
@@ -88,6 +88,9 @@ function pieOption1(value, text, subtext) {
 }
 
 function barOption1(avgTotal, avgCorrect, avgIncorrent) {
+  avgTotal = parseInt(avgTotal, 10);
+  avgCorrect = parseInt(avgCorrect, 10);
+  avgIncorrent = parseInt(avgIncorrent, 10);
   return {
     xAxis: {
       type: 'category',
@@ -259,7 +262,7 @@ function barOption3(titles, source, data1, data2, color1, color2) {
         yAxisIndex: 0,
         barWidth: 24,
         data: data1.map((item, index) => ({
-          value: item,
+          value: formatPercent(item[0], item[1], true),
           itemStyle: { color: index % 2 ? color1[0] : color1[1] },
           label: {
             show: true,
@@ -267,7 +270,7 @@ function barOption3(titles, source, data1, data2, color1, color2) {
             align: 'right',
             position: [250, 5],
             fontSize: 12,
-            formatter: item,
+            formatter: `${item[0]}/${item[1]} ${formatPercent(item[0], item[1], false)}`,
           },
         })),
       },
@@ -277,7 +280,7 @@ function barOption3(titles, source, data1, data2, color1, color2) {
         yAxisIndex: 1,
         barWidth: 24,
         data: data2.map((item, index) => ({
-          value: item,
+          value: parseInt(item, 10),
           itemStyle: { color: index % 2 ? color2[0] : color2[1] },
           label: {
             show: true,
@@ -285,7 +288,7 @@ function barOption3(titles, source, data1, data2, color1, color2) {
             align: 'right',
             fontSize: 12,
             position: [260, 5],
-            formatter: item,
+            formatter: formatMinuteSecond(parseInt(item, 10)),
           },
         })),
       },
@@ -510,7 +513,7 @@ export default class extends Page {
               return row.key;
             }),
             data.place.map(row => {
-              return formatPercent(row.userCorrect, row.userNumber);
+              return [row.userCorrect, row.userNumber];
             }),
             data.place.map(row => {
               return row.userTime / row.userNumber;

+ 7 - 5
front/project/www/routes/my/main/page.js

@@ -20,6 +20,7 @@ import VipRenew from '../../../components/VipRenew';
 import { My } from '../../../stores/my';
 import { Main } from '../../../stores/main';
 import { QuestionType } from '../../../../Constant';
+import { User } from '../../../stores/user';
 
 const QuestionTypeMap = getMap(QuestionType, 'value', 'label');
 
@@ -241,6 +242,7 @@ export default class extends Page {
 
   readAllMessage() {
     My.readAllMessage().then(() => {
+      User.refreshToken();
       asyncSMessage('操作成功');
     });
   }
@@ -277,7 +279,7 @@ export default class extends Page {
           { title: '<span>练习和订正</span>', width: 130 },
           {
             title: result.exerciseTime
-              ? formatSeconds(result.exerciseTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2')
+              ? formatSeconds(result.exerciseTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '<b>$1</b>$2')
               : '<b>-</b>',
             width: 90,
           },
@@ -314,7 +316,7 @@ export default class extends Page {
           { title: '<span>模考和订正</span>', width: 130 },
           {
             title: result.examinationTime
-              ? formatSeconds(result.examinationTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2')
+              ? formatSeconds(result.examinationTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '<b>$1</b>$2')
               : '<b>-</b>',
             width: 90,
           },
@@ -338,7 +340,7 @@ export default class extends Page {
           { title: '<span>课程学习</span>', width: 130 },
           {
             title: result.courseTime
-              ? formatSeconds(result.courseTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2')
+              ? formatSeconds(result.courseTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '<b>$1</b>$2')
               : '<b>-</b>',
             width: 90,
           },
@@ -411,7 +413,7 @@ export default class extends Page {
           <div className="right">
             <span
               dangerouslySetInnerHTML={{
-                __html: `本周学习时间${formatSeconds(latest.time).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2')}`,
+                __html: `本周学习时间${formatSeconds(latest.time).replace(/([0-9]+)(min|m|hour|h|s)/g, '<b>$1</b>$2')}`,
               }}
             />
             <span>
@@ -483,7 +485,7 @@ export default class extends Page {
             天,累计
             <span
               dangerouslySetInnerHTML={{
-                __html: formatSeconds(total.time).replace(/([0-9]+)(m|min|h|hour|s)/g, '<b>$1</b>$2'),
+                __html: formatSeconds(total.time).replace(/([0-9]+)(min|m|hour|h|s)/g, '<b>$1</b>$2'),
               }}
             />
           </div>

+ 2 - 0
front/project/www/routes/my/message/page.js

@@ -10,6 +10,7 @@ import Tabs from '../../../components/Tabs';
 import { My } from '../../../stores/my';
 import { MessageType } from '../../../../Constant';
 import { getMap, formatDate } from '../../../../../src/services/Tools';
+import { User } from '../../../stores/user';
 
 const MessageTypeMap = getMap(MessageType, 'value', 'label');
 
@@ -95,6 +96,7 @@ export default class extends Page {
   readAllMessage() {
     My.readAllMessage().then(() => {
       asyncSMessage('操作成功');
+      User.refreshToken();
       this.refresh();
     });
   }

+ 3 - 4
front/project/www/routes/page/export/page.js

@@ -101,8 +101,7 @@ export default class extends Page {
       <div className="detail-layout">
         <div className="content">
           {list.map(item => {
-            return [this.renderTotal(item),
-              item.question.questionType === 'sentence' ? <SentenceDetail data={item} /> : <BaseDetail data={item} />];
+            return [this.renderTotal(item), item.question.questionType === 'sentence' ? <SentenceDetail data={item} /> : <BaseDetail data={item} />];
           })}
         </div>
       </div>
@@ -122,7 +121,7 @@ export default class extends Page {
             <span
               dangerouslySetInnerHTML={{
                 __html: formatSeconds(userTime).replace(
-                  /([0-9]+)(m|min|h|hour|s)/g,
+                  /([0-9]+)(min|m|hour|h|s)/g,
                   '<span class="t-4">$1</span>$2',
                 ),
               }}
@@ -133,7 +132,7 @@ export default class extends Page {
             <span
               dangerouslySetInnerHTML={{
                 __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(
-                  /([0-9]+)(m|min|h|hour|s)/g,
+                  /([0-9]+)(min|m|hour|h|s)/g,
                   '<span class="t-4">$1</span>$2',
                 ),
               }}

+ 2 - 2
front/project/www/routes/paper/process/sentence/index.js

@@ -154,7 +154,7 @@ export default class extends Component {
             用时:
             <span
               dangerouslySetInnerHTML={{
-                __html: formatSeconds(userQuestion.userTime).replace(/([0-9]+)(m|min|h|hour|s)/g, '<span class="s">$1</span>$2'),
+                __html: formatSeconds(userQuestion.userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '<span class="s">$1</span>$2'),
               }}
             />
             {/* 用时:<span className="s">1</span>m<span className="s">39</span>s */}
@@ -164,7 +164,7 @@ export default class extends Component {
             <span
               dangerouslySetInnerHTML={{
                 __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(
-                  /([0-9]+)(m|min|h|hour|s)/g,
+                  /([0-9]+)(min|m|hour|h|s)/g,
                   '<span class="s">$1</span>$2',
                 ),
               }}

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

@@ -39,17 +39,17 @@ export default class extends Component {
   }
 
   prevQuestion() {
-    const { userQuestion } = this.props;
+    const { userQuestion, report } = this.props;
     if (userQuestion.no === 1) return;
-    Question.getDetailByNo(userQuestion.reportId, userQuestion.no - 1).then(r => {
+    Question.getDetailByNo(report.id, userQuestion.no - 1).then(r => {
       linkTo(`/paper/question/${r.id}`);
     });
   }
 
   nextQuestion() {
-    const { userQuestion } = this.props;
+    const { userQuestion, report } = this.props;
     if (userQuestion.questionNumber === userQuestion.no) return;
-    Question.getDetailByNo(userQuestion.reportId, userQuestion.no + 1).then(r => {
+    Question.getDetailByNo(report.id, userQuestion.no + 1).then(r => {
       linkTo(`/paper/question/${r.id}`);
     });
   }
@@ -304,7 +304,7 @@ export default class extends Component {
               <span
                 dangerouslySetInnerHTML={{
                   __html: formatSeconds(userQuestion.userTime).replace(
-                    /([0-9]+)(m|min|h|hour|s)/g,
+                    /([0-9]+)(min|m|hour|h|s)/g,
                     '<span class="s">$1</span>$2',
                   ),
                 }}
@@ -317,7 +317,7 @@ export default class extends Component {
             <span
               dangerouslySetInnerHTML={{
                 __html: formatSeconds(questionNo.totalTime / questionNo.totalNumber).replace(
-                  /([0-9]+)(m|min|h|hour|s)/g,
+                  /([0-9]+)(min|m|hour|h|s)/g,
                   '<span class="s">$1</span>$2',
                 ),
               }}
@@ -626,7 +626,7 @@ export default class extends Component {
                   <span
                     dangerouslySetInnerHTML={{
                       __html: formatSeconds(userQuestion.userTime).replace(
-                        /([0-9]+)(m|min|h|hour|s)/g,
+                        /([0-9]+)(min|m|hour|h|s)/g,
                         '<span class="s">$1</span>$2',
                       ),
                     }}

+ 76 - 75
front/project/www/routes/paper/report/page.js

@@ -89,7 +89,7 @@ function BarOption3(titles, source, data1, data2, color1, color2) {
         yAxisIndex: 0,
         barWidth: 30,
         data: data1.map((item, index) => ({
-          value: item,
+          value: formatPercent(item[0], item[1], true),
           itemStyle: { color: index % 2 ? color1[0] : color1[1] },
           label: {
             show: true,
@@ -97,7 +97,7 @@ function BarOption3(titles, source, data1, data2, color1, color2) {
             align: 'right',
             position: [360, 5],
             fontSize: 16,
-            formatter: item,
+            formatter: `${item[0]}/${item[1]} ${formatPercent(item[0], item[1], false)}`,
           },
         })),
       },
@@ -107,7 +107,7 @@ function BarOption3(titles, source, data1, data2, color1, color2) {
         yAxisIndex: 1,
         barWidth: 30,
         data: data2.map((item, index) => ({
-          value: item,
+          value: parseInt(item, 10),
           itemStyle: { color: index % 2 ? color2[0] : color2[1] },
           label: {
             show: true,
@@ -115,7 +115,7 @@ function BarOption3(titles, source, data1, data2, color1, color2) {
             align: 'right',
             fontSize: 16,
             position: [360, 5],
-            formatter: item,
+            formatter: formatMinuteSecond(parseInt(item, 10)),
           },
         })),
       },
@@ -130,7 +130,7 @@ function BarOption2(title, data, legend, color) {
       textStyle: { fontSize: 24, fontWeight: 'bold', color: '#686872' },
     },
     tooltip: {
-      trigger: 'axis',
+      trigger: 'item',
     },
     legend: {
       show: legend.length > 1,
@@ -169,7 +169,10 @@ function lineOption1(title, data, legend, color) {
       left: '0',
     },
     tooltip: {
-      trigger: 'axis',
+      trigger: 'item',
+      formatter: (params) => {
+        return formatSeconds(params.value[params.seriesIndex + 1]);
+      },
     },
     legend: {
       show: legend.length > 1,
@@ -202,6 +205,10 @@ function lineOption1(title, data, legend, color) {
 }
 
 function barOption1(title, value, allValue, avgCorrect, avgIncorrent) {
+  value = parseInt(value, 10);
+  allValue = parseInt(allValue, 10);
+  avgCorrect = parseInt(avgCorrect, 10);
+  avgIncorrent = parseInt(avgIncorrent, 10);
   const xAxis1 = [
     {
       gridIndex: 0,
@@ -274,7 +281,7 @@ function barOption1(title, value, allValue, avgCorrect, avgIncorrent) {
         label: {
           show: true,
           position: 'top',
-          formatter: `{a|${value}}`,
+          formatter: `{a|${formatSeconds(value)}}`,
           rich: { a: { fontSize: 16, fontWeight: 'bold', color: '#686872' } },
         },
       },
@@ -284,7 +291,7 @@ function barOption1(title, value, allValue, avgCorrect, avgIncorrent) {
         label: {
           show: true,
           position: 'top',
-          formatter: `{a|${allValue}}`,
+          formatter: `{a|全站${formatSeconds(allValue)}}`,
           rich: { a: { fontSize: 12, color: '#686872' } },
         },
       },
@@ -303,7 +310,7 @@ function barOption1(title, value, allValue, avgCorrect, avgIncorrent) {
         label: {
           show: true,
           position: 'top',
-          formatter: `{a|${avgCorrect}}`,
+          formatter: `{a|${formatSeconds(avgCorrect)}}`,
           rich: { a: { fontSize: 16, fontWeight: 'bold', color: '#686872' } },
         },
       },
@@ -314,7 +321,7 @@ function barOption1(title, value, allValue, avgCorrect, avgIncorrent) {
         label: {
           show: true,
           position: 'top',
-          formatter: `{a|${avgIncorrent}}`,
+          formatter: `{a|${formatSeconds(avgIncorrent)}}`,
           rich: { a: { fontSize: 16, fontWeight: 'bold', color: '#686872' } },
         },
       },
@@ -529,42 +536,46 @@ export default class extends Page {
         default:
       }
       this.setState({ report: result, paper: result.paper });
-    });
-    switch (info) {
-      case 'question':
-        // 题目回顾列表
-        Question.questionReport(id).then(result => {
-          switch (result.paperModule) {
-            case 'sentence':
-              result = result.map((row) => {
-                row.struct = row.detail.subject && row.detail.predicate && row.detail.object ? 0 : 1;
-                row.logic = row.detail.options ? 0 : 1;
+      return result;
+    })
+      .then(report => {
+        switch (info) {
+          case 'question':
+            // 题目回顾列表
+            Question.questionReport(id).then(result => {
+              switch (report.paperModule) {
+                case 'sentence':
+                  result = result.map((row) => {
+                    row.struct = row.detail.subject && row.detail.predicate && row.detail.object ? 0 : 1;
+                    row.logic = row.detail.options ? 0 : 1;
 
-                row.note = row.note ? 1 : 0;
-                row.collect = row.collect ? 1 : 0;
-                return row;
-              });
-              break;
-            case 'textbook':
-            case 'exercise':
-              result = result.map((row) => {
-                row.correct = row.isCorrect ? 0 : 1;
-                row.diff = QuestionDifficultSort[row.question.difficult];
+                    row.note = row.note ? 1 : 0;
+                    row.collect = row.collect ? 1 : 0;
+                    return row;
+                  });
+                  break;
+                case 'textbook':
+                case 'exercise':
+                  result = result.map((row) => {
+                    row.correct = row.isCorrect ? 0 : 1;
+                    row.difficult = QuestionDifficultSort[row.question.difficult];
+                    row.place = row.question.place;
 
-                row.note = row.note ? 1 : 0;
-                row.collect = row.collect ? 1 : 0;
-                return row;
-              });
-              this.refreshExercise(result);
-              break;
-            default:
-          }
-          this.setState({ list: result });
-        });
-        break;
-      default:
-        break;
-    }
+                    row.note = row.note ? 1 : 0;
+                    row.collect = row.collect ? 1 : 0;
+                    return row;
+                  });
+                  this.refreshExercise(result);
+                  break;
+                default:
+              }
+              this.setState({ list: result });
+            });
+            break;
+          default:
+            break;
+        }
+      });
   }
 
   refreshSentence() {
@@ -608,11 +619,11 @@ export default class extends Page {
       order = field;
       // direction = 'desc';
     }
-    list.sort((a, b) => {
+    list.sort((b, a) => {
       const aValue = a[order];
-      const bValue = a[order];
+      const bValue = b[order];
       if (aValue === bValue) {
-        return a.no < b.no ? -1 : a.no > b.no ? 1 : 0;
+        return b.no - a.no;
       }
       return aValue > bValue ? -1 : 1;
     });
@@ -849,13 +860,11 @@ export default class extends Page {
           <div className="detail">
             <div className="block">
               <div className="t1">总耗时</div>
-              <div className="t2">{formatMinute(detail.info.userTime, true)}</div>
-              <div className="t3">min</div>
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(detail.info.userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>
             {detail.info.userTime > detail.info.time && <div className="block">
               <div className="t1">超出建议用时</div>
-              <div className="t2">{formatMinute(detail.info.userTime - detail.info.time, true)}</div>
-              <div className="t3">min</div>
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(detail.info.userTime - detail.info.time).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>}
             <div className="line" />
             <div className="block">
@@ -923,8 +932,8 @@ export default class extends Page {
                   this.questionSort('correct');
                 }}>正误<GIcon name={order === 'correct' ? 'arrow-down' : 'arrow-up'} active={order === 'correct'} /></th>
                 <th className="point" onClick={() => {
-                  this.questionSort('diff');
-                }}>难度<GIcon name={order === 'diff' ? 'arrow-down' : 'arrow-up'} active={order === 'diff'} /></th>
+                  this.questionSort('difficult');
+                }}>难度<GIcon name={order === 'difficult' ? 'arrow-down' : 'arrow-up'} active={order === 'difficult'} /></th>
                 <th className="point" onClick={() => {
                   this.questionSort('userTime');
                 }}>用时<GIcon name={order === 'userTime' ? 'arrow-down' : 'arrow-up'} active={order === 'userTime'} /></th>
@@ -978,13 +987,11 @@ export default class extends Page {
           <div className="detail">
             <div className="block">
               <div className="t1">总耗时</div>
-              <div className="t2">{formatMinute(info.userTime, true)}</div>
-              <div className="t3">min</div>
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>
             {info.userTime > info.time && <div className="block">
               <div className="t1">超出建议用时</div>
-              <div className="t2">{formatMinute(info.userTime - info.time, true)}</div>
-              <div className="t3">min</div>
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.userTime - info.time).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>}
             <div className="line" />
             <div className="block">
@@ -1019,11 +1026,11 @@ export default class extends Page {
           <div className="detail-1">
             <div className="block">
               <div className="t1">平均用时</div>
-              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.userTime / info.userNumber).replace(/([0-9]+)(m|min|h|hour|s)/g, '$1<div class="t3">$2</div>') }} />
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.userTime / info.userNumber).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>
             <div className="block all">
               <div className="t1">全站用户</div>
-              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.totalTime / info.totalNumber).replace(/([0-9]+)(m|min|h|hour|s)/g, '$1<div class="t3">$2</div>') }} />
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.totalTime / info.totalNumber).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>
           </div>
           <LineChart
@@ -1072,7 +1079,7 @@ export default class extends Page {
           <div className="detail-1">
             <div className="block">
               <div className="t1">平均用时</div>
-              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.userTime / info.userNumber).replace(/([0-9]+)(m|min|h|hour|s)/g, '$1<div class="t3">$2</div>') }} />
+              <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(info.userTime / info.userNumber).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
             </div>
             <div className="block all">
               <div className="t1">正确率</div>
@@ -1087,7 +1094,7 @@ export default class extends Page {
                 return row.key;
               }),
               place.map(row => {
-                return formatPercent(row.userCorrect, row.userNumber);
+                return [row.userCorrect, row.userNumber];
               }),
               place.map(row => {
                 return row.userTime / row.userNumber;
@@ -1160,31 +1167,25 @@ export default class extends Page {
               <div className="block">
                 <div className="t1">总耗时</div>
                 <div className="t1">
-                  <div className="t2">{formatMinute((subject.verbal || {}).userTime, true)}</div>
-                  <div className="t3">min</div>
+                  <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds((subject.verbal || {}).userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
                 </div>
                 <div className="t1">
-                  <div className="t2">{formatMinute((subject.quant || {}).userTime, true)}</div>
-                  <div className="t3">min</div>
+                  <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds((subject.quant || {}).userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
                 </div>
                 <div className="t1">
-                  <div className="t2">{formatMinute((subject.ir || {}).userTime, true)}</div>
-                  <div className="t3">min</div>
+                  <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds((subject.ir || {}).userTime).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
                 </div>
               </div>
               <div className="block">
                 <div className="t1">超出建议用时</div>
                 <div className="t1">
-                  <div className="t2">{formatMinute((subject.verbal || {}).userTime - (subject.verbal || {}).time, true)}</div>
-                  <div className="t3">min</div>
+                  <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds((subject.verbal || {}).userTime - (subject.verbal || {}).time).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
                 </div>
                 <div className="t1">
-                  <div className="t2">{formatMinute((subject.quant || {}).userTime - (subject.quant || {}).time, true)}</div>
-                  <div className="t3">min</div>
+                  <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds((subject.quant || {}).userTime - (subject.quant || {}).time).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
                 </div>
                 <div className="t1">
-                  <div className="t2">{formatMinute((subject.ir || {}).userTime - (subject.ir || {}).time, true)}</div>
-                  <div className="t3">min</div>
+                  <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds((subject.ir || {}).userTime - (subject.ir || {}).time).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
                 </div>
               </div>
               <div className="block">
@@ -1235,7 +1236,7 @@ export default class extends Page {
             <div className="detail-1">
               <div className="block">
                 <div className="t1">平均用时</div>
-                <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(subjectDetail.info.userTime / subjectDetail.info.userNumber).replace(/([0-9]+)(m|min|h|hour|s)/g, '$1<div class="t3">$2</div>') }} />
+                <div className="t2" dangerouslySetInnerHTML={{ __html: formatSeconds(subjectDetail.info.userTime / subjectDetail.info.userNumber).replace(/([0-9]+)(min|m|hour|h|s)/g, '$1<div class="t3">$2</div>') }} />
               </div>
             </div>
             <LineChart
@@ -1418,7 +1419,7 @@ export default class extends Page {
                 return row.key;
               }),
               subjectDetail.place.map(row => {
-                return formatPercent(row.userCorrect, row.userNumber);
+                return [row.userCorrect, row.userNumber];
               }),
               subjectDetail.place.map(row => {
                 return row.userTime / row.userNumber;

+ 2 - 2
front/project/www/routes/preview/list/page.js

@@ -100,9 +100,9 @@ export default class extends Page {
               {(record.report && !record.report.isFinish) && <IconButton className="m-r-2" type="continue" tip="Continue" onClick={() => {
                 Question.continueLink('exercise', record);
               }} />}
-              <IconButton type="restart" tip="Restart" onClick={() => {
+              {(record.report) && <IconButton type="restart" tip="Restart" onClick={() => {
                 this.restart(record);
-              }} />
+              }} />}
             </div>
           );
         },

+ 2 - 2
front/project/www/routes/textbook/list/page.js

@@ -92,9 +92,9 @@ export default class extends Page {
             {(record.report && !record.report.isFinish) && <IconButton className="m-r-2" type="continue" tip="Continue" onClick={() => {
               Question.continueLink('exercise', record);
             }} />}
-            <IconButton type="restart" tip="Restart" onClick={() => {
+            {(record.report) && <IconButton type="restart" tip="Restart" onClick={() => {
               this.restart(record);
-            }} />
+            }} />}
           </div>
         );
       },

+ 2 - 2
server/data/src/main/java/com/qxgmat/data/relation/mapping/ExaminationPaperRelationMapper.xml

@@ -52,7 +52,7 @@
       </if>
       <if test="times != null">
         <if test="times == 0">
-          and up.`times` = 0
+          and up.`times` > 0
         </if>
         <if test="times > 0">
           and up.`times` >= #{times,jdbcType=VARCHAR}
@@ -65,7 +65,7 @@
     </if>
     <if test="userId != null">
       <if test="times == 0">
-        and (up.`id` &gt; 0 or up.`id` is null)
+        and up.`id` is null
       </if>
       <if test="times > 0">
         and up.`id` &gt; 0

+ 2 - 2
server/data/src/main/java/com/qxgmat/data/relation/mapping/ExercisePaperRelationMapper.xml

@@ -45,7 +45,7 @@
       and up.`user_id` = #{userId,jdbcType=VARCHAR}
       <if test="times != null">
         <if test="times == 0">
-          and up.`times` = 0
+          and up.`times` > 0
         </if>
         <if test="times > 0">
           and up.`times` >= #{times,jdbcType=VARCHAR}
@@ -58,7 +58,7 @@
     </if>
     <if test="userId != null">
       <if test="times == 0">
-        and (up.`id` &gt; 0 or up.`id` is null)
+        and up.`id` is null
       </if>
       <if test="times > 0">
         and up.`id` &gt; 0

+ 6 - 6
server/data/src/main/java/com/qxgmat/data/relation/mapping/PreviewAssignRelationMapper.xml

@@ -27,7 +27,7 @@
       and up.`user_id` = #{userId,jdbcType=VARCHAR}
       <if test="times != null">
         <if test="times == 0">
-          and up.`times` = 0
+          and up.`times` > 0
         </if>
         <if test="times > 0">
           and up.`times` >= #{times,jdbcType=VARCHAR}
@@ -40,7 +40,7 @@
     </if>
     <if test="userId != null">
       <if test="times == 0">
-        and (up.`id` &gt; 0 or up.`id` is null)
+        and up.`id` is null
       </if>
       <if test="times > 0">
         and up.`id` &gt; 0
@@ -61,7 +61,7 @@
       and up.`user_id` = #{userId,jdbcType=VARCHAR}
       <if test="times != null">
         <if test="times == 0">
-          and up.`times` = 0
+          and up.`times` > 0
         </if>
         <if test="times > 0">
           and up.`times` >= #{times,jdbcType=VARCHAR}
@@ -80,7 +80,7 @@
     </if>
     <if test="userId != null">
       <if test="times == 0">
-        and (up.`id` &gt; 0 or up.`id` is null)
+        and up.`id` is null
       </if>
       <if test="times > 0">
         and up.`id` &gt; 0
@@ -101,7 +101,7 @@
       and up.`user_id` = #{userId,jdbcType=VARCHAR}
       <if test="times != null">
         <if test="times == 0">
-          and up.`times` = 0
+          and up.`times` > 0
         </if>
         <if test="times > 0">
           and up.`times` >= #{times,jdbcType=VARCHAR}
@@ -117,7 +117,7 @@
     </if>
     <if test="userId != null">
       <if test="times == 0">
-        and (up.`id` &gt; 0 or up.`id` is null)
+        and up.`id` is null
       </if>
       <if test="times > 0">
         and up.`id` &gt; 0

+ 2 - 2
server/data/src/main/java/com/qxgmat/data/relation/mapping/TextbookPaperRelationMapper.xml

@@ -27,7 +27,7 @@
       and up.`user_id` = #{userId,jdbcType=VARCHAR}
       <if test="times != null">
         <if test="times == 0">
-          and up.`times` = 0
+          and up.`times` > 0
         </if>
         <if test="times > 0">
           and up.`times` >= #{times,jdbcType=VARCHAR}
@@ -43,7 +43,7 @@
     </if>
     <if test="userId != null">
       <if test="times == 0">
-        and (up.`id` &gt; 0 or up.`id` is null)
+        and up.`id` is null
       </if>
       <if test="times > 0">
         and up.`id` &gt; 0

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/dto/response/UserReportBaseDto.java

@@ -18,7 +18,7 @@ public class UserReportBaseDto {
     private String paperModule;
 
     private String paperOrigin;
-    
+
     private Integer originId;
 
     private Integer time;

+ 1 - 1
server/gateway-api/src/main/java/com/qxgmat/service/inline/ExercisePaperService.java

@@ -80,7 +80,7 @@ public class ExercisePaperService extends AbstractService {
      * @return
      */
     public String generateTitle(String prefixTitle, Integer length, Integer no, Integer questionNumber){
-        return String.format("%s#%d~%d", prefixTitle, (no - 1) * length + 1, (no - 1) * length + questionNumber);
+        return String.format("%s(%d-%d)", prefixTitle, (no - 1) * length + 1, (no - 1) * length + questionNumber);
     }
 
     /**

+ 2 - 2
server/gateway-api/src/main/java/com/qxgmat/task/AsyncTask.java

@@ -107,7 +107,7 @@ public class AsyncTask {
             List<Integer> allDifficultIds = new ArrayList<>();
             for(QuestionDifficult difficult : QuestionDifficult.all()){
                 List<QuestionNoRelation> difficultList = list.stream().filter((question)-> question.getQuestion().getDifficult().equals(difficult.key)).collect(Collectors.toList());
-                List<ExercisePaper> difficultPapers = exerciseService.createPaper(String.format("%s %s", prefixTitle, difficult.key), questionType, struct.getParentId(), struct.getId(), exerciseService.getPaperLength(), ExerciseLogic.DIFFICULT, difficult.key, difficultList);
+                List<ExercisePaper> difficultPapers = exerciseService.createPaper(String.format("%s-%s", prefixTitle, difficult.key), questionType, struct.getParentId(), struct.getId(), exerciseService.getPaperLength(), ExerciseLogic.DIFFICULT, difficult.key, difficultList);
                 Collection difficultIds = Transform.getIds(difficultPapers, ExercisePaper.class, "id");
                 allDifficultIds.addAll(difficultIds);
             }
@@ -126,7 +126,7 @@ public class AsyncTask {
             List<Integer> allPlaceIds = new ArrayList<>();
             for(String place: placeMap.keySet()){
                 List<QuestionNoRelation> placeList = placeMap.get(place);
-                List<ExercisePaper> difficultPapers = exerciseService.createPaper(String.format("%s %s", prefixTitle, place), questionType, struct.getParentId(), struct.getId(), exerciseService.getPaperLength(), ExerciseLogic.PLACE, place, placeList);
+                List<ExercisePaper> difficultPapers = exerciseService.createPaper(String.format("%s-%s", prefixTitle, place), questionType, struct.getParentId(), struct.getId(), exerciseService.getPaperLength(), ExerciseLogic.PLACE, place, placeList);
                 Collection placeIds = Transform.getIds(difficultPapers, ExercisePaper.class, "id");
                 allPlaceIds.addAll(placeIds);
             }