Browse Source

Merge branch 'develop6.0-tmd' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop6.0-tmd

Li 3 years ago
parent
commit
56e5570c41
34 changed files with 2500 additions and 1857 deletions
  1. 2 1
      TEAMModelOS/ClientApp/public/web/viewer.css
  2. 456 375
      TEAMModelOS/ClientApp/public/web/viewer.html
  3. 36 41
      TEAMModelOS/ClientApp/src/api/http.js
  4. 5 1
      TEAMModelOS/ClientApp/src/api/studentWeb.js
  5. 17 0
      TEAMModelOS/ClientApp/src/assets/student-web/component_styles/course-content.less
  6. 0 1
      TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.vue
  7. 2 2
      TEAMModelOS/ClientApp/src/components/research-dashboard/LeftTop.vue
  8. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.vue
  9. 24 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue
  10. 281 0
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/QuCount.vue
  11. 12 1
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/ScoreBarChart.vue
  12. 40 2
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue
  13. 104 29
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseListView.vue
  14. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js
  15. 6 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/studentWeb.js
  16. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/learnActivity.js
  17. 6 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js
  18. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js
  19. 6 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/studentWeb.js
  20. 40 41
      TEAMModelOS/ClientApp/src/view/Home.vue
  21. 15 1
      TEAMModelOS/ClientApp/src/view/assessment/Assessment.vue
  22. 0 2
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.less
  23. 58 55
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  24. 7 2
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/Receive.vue
  25. 1 1
      TEAMModelOS/ClientApp/src/view/dashboard/Research.vue
  26. 3 3
      TEAMModelOS/ClientApp/src/view/jyzx/classMemoir.vue
  27. 26 21
      TEAMModelOS/ClientApp/src/view/learnactivity/ExamMgt.vue
  28. 18 11
      TEAMModelOS/ClientApp/src/view/learnactivity/echarts/KngPoint.vue
  29. 1 1
      TEAMModelOS/ClientApp/src/view/learnactivity/tabs/AnswerTable.less
  30. 1 0
      TEAMModelOS/ClientApp/src/view/learnactivity/tabs/AnswerTable.vue
  31. 68 0
      TEAMModelOS/ClientApp/src/view/learnactivity/tabs/CrossSchool.vue
  32. 1 1
      TEAMModelOS/ClientApp/src/view/learnactivity/tabs/DataView.less
  33. 69 8
      TEAMModelOS/ClientApp/src/view/newcourse/ClassTable.vue
  34. 1190 1252
      TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue

+ 2 - 1
TEAMModelOS/ClientApp/public/web/viewer.css

@@ -822,9 +822,10 @@ select {
 #sidebarContainer {
   position: absolute;
   top: 32px;
+  left:0;
   bottom: 0;
   width: var(--sidebar-width);
-  visibility: hidden;
+  /* visibility: hidden; */
   z-index: 100;
   border-top: 1px solid rgba(51, 51, 51, 1);
   transition-duration: var(--sidebar-transition-duration);

+ 456 - 375
TEAMModelOS/ClientApp/public/web/viewer.html

@@ -21,379 +21,460 @@ Adobe CMap resources are covered by their own copyright but the same license:
 See https://github.com/adobe-type-tools/cmap-resources
 -->
 <html dir="ltr" mozdisallowselectionprint>
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
-    <meta name="google" content="notranslate">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <title>PDF.js viewer</title>
-
-
-    <link rel="stylesheet" href="viewer.css">
-
-
-<!-- This snippet is used in production (included from viewer.html) -->
-<link rel="resource" type="application/l10n" href="locale/locale.properties">
-<script src="../pdfBuild/pdf.js"></script>
-
-
-  <script src="viewer.js" charset="gb2312"></script>
-
-  </head>
-
-  <body tabindex="1">
-    <div id="outerContainer">
-
-      <div id="sidebarContainer">
-        <div id="toolbarSidebar">
-          <div id="toolbarSidebarLeft">
-            <div class="splitToolbarButton toggled">
-              <button id="viewThumbnail" class="toolbarButton toggled" title="Show Thumbnails" tabindex="2" data-l10n-id="thumbs">
-                 <span data-l10n-id="thumbs_label">Thumbnails</span>
-              </button>
-              <button id="viewOutline" class="toolbarButton" title="Show Document Outline (double-click to expand/collapse all items)" tabindex="3" data-l10n-id="document_outline">
-                 <span data-l10n-id="document_outline_label">Document Outline</span>
-              </button>
-              <button id="viewAttachments" class="toolbarButton" title="Show Attachments" tabindex="4" data-l10n-id="attachments">
-                 <span data-l10n-id="attachments_label">Attachments</span>
-              </button>
-              <button id="viewLayers" class="toolbarButton" title="Show Layers (double-click to reset all layers to the default state)" tabindex="5" data-l10n-id="layers">
-                 <span data-l10n-id="layers_label">Layers</span>
-              </button>
-            </div>
-          </div>
-
-          <div id="toolbarSidebarRight">
-            <div id="outlineOptionsContainer" class="hidden">
-              <div class="verticalToolbarSeparator"></div>
-
-              <button id="currentOutlineItem" class="toolbarButton" disabled="disabled" title="Find Current Outline Item" tabindex="6" data-l10n-id="current_outline_item">
-                <span data-l10n-id="current_outline_item_label">Current Outline Item</span>
-              </button>
-            </div>
-          </div>
-        </div>
-        <div id="sidebarContent">
-          <div id="thumbnailView">
-          </div>
-          <div id="outlineView" class="hidden">
-          </div>
-          <div id="attachmentsView" class="hidden">
-          </div>
-          <div id="layersView" class="hidden">
-          </div>
-        </div>
-        <div id="sidebarResizer"></div>
-      </div>  <!-- sidebarContainer -->
-
-      <div id="mainContainer">
-        <div class="findbar hidden doorHanger" id="findbar">
-          <div id="findbarInputContainer">
-            <input id="findInput" class="toolbarField" title="Find" placeholder="Find in document…" tabindex="91" data-l10n-id="find_input">
-            <div class="splitToolbarButton">
-              <button id="findPrevious" class="toolbarButton findPrevious" title="Find the previous occurrence of the phrase" tabindex="92" data-l10n-id="find_previous">
-                <span data-l10n-id="find_previous_label">Previous</span>
-              </button>
-              <div class="splitToolbarButtonSeparator"></div>
-              <button id="findNext" class="toolbarButton findNext" title="Find the next occurrence of the phrase" tabindex="93" data-l10n-id="find_next">
-                <span data-l10n-id="find_next_label">Next</span>
-              </button>
-            </div>
-          </div>
-
-          <div id="findbarOptionsOneContainer">
-            <input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94">
-            <label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight all</label>
-            <input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
-            <label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match case</label>
-          </div>
-          <div id="findbarOptionsTwoContainer">
-            <input type="checkbox" id="findEntireWord" class="toolbarField" tabindex="96">
-            <label for="findEntireWord" class="toolbarLabel" data-l10n-id="find_entire_word_label">Whole words</label>
-            <span id="findResultsCount" class="toolbarLabel hidden"></span>
-          </div>
-
-          <div id="findbarMessageContainer">
-            <span id="findMsg" class="toolbarLabel"></span>
-          </div>
-        </div>  <!-- findbar -->
-
-        <div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
-          <div id="secondaryToolbarButtonContainer">
-            <button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="51" data-l10n-id="presentation_mode">
-              <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
-            </button>
-
-            <button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="52" data-l10n-id="open_file">
-              <span data-l10n-id="open_file_label">Open</span>
-            </button>
-
-            <button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="53" data-l10n-id="print">
-              <span data-l10n-id="print_label">Print</span>
-            </button>
-
-            <button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="54" data-l10n-id="download">
-              <span data-l10n-id="download_label">Download</span>
-            </button>
-
-            <a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="55" data-l10n-id="bookmark">
-              <span data-l10n-id="bookmark_label">Current View</span>
-            </a>
-
-            <div class="horizontalToolbarSeparator visibleLargeView"></div>
-
-            <button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="56" data-l10n-id="first_page">
-              <span data-l10n-id="first_page_label">Go to First Page</span>
-            </button>
-            <button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="57" data-l10n-id="last_page">
-              <span data-l10n-id="last_page_label">Go to Last Page</span>
-            </button>
-
-            <div class="horizontalToolbarSeparator"></div>
-
-            <button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="58" data-l10n-id="page_rotate_cw">
-              <span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
-            </button>
-            <button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="59" data-l10n-id="page_rotate_ccw">
-              <span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
-            </button>
-
-            <div class="horizontalToolbarSeparator"></div>
-
-            <button id="cursorSelectTool" class="secondaryToolbarButton selectTool toggled" title="Enable Text Selection Tool" tabindex="60" data-l10n-id="cursor_text_select_tool">
-              <span data-l10n-id="cursor_text_select_tool_label">Text Selection Tool</span>
-            </button>
-            <button id="cursorHandTool" class="secondaryToolbarButton handTool" title="Enable Hand Tool" tabindex="61" data-l10n-id="cursor_hand_tool">
-              <span data-l10n-id="cursor_hand_tool_label">Hand Tool</span>
-            </button>
-
-            <div class="horizontalToolbarSeparator"></div>
-
-            <button id="scrollVertical" class="secondaryToolbarButton scrollModeButtons scrollVertical toggled" title="Use Vertical Scrolling" tabindex="62" data-l10n-id="scroll_vertical">
-              <span data-l10n-id="scroll_vertical_label">Vertical Scrolling</span>
-            </button>
-            <button id="scrollHorizontal" class="secondaryToolbarButton scrollModeButtons scrollHorizontal" title="Use Horizontal Scrolling" tabindex="63" data-l10n-id="scroll_horizontal">
-              <span data-l10n-id="scroll_horizontal_label">Horizontal Scrolling</span>
-            </button>
-            <button id="scrollWrapped" class="secondaryToolbarButton scrollModeButtons scrollWrapped" title="Use Wrapped Scrolling" tabindex="64" data-l10n-id="scroll_wrapped">
-              <span data-l10n-id="scroll_wrapped_label">Wrapped Scrolling</span>
-            </button>
-
-            <div class="horizontalToolbarSeparator scrollModeButtons"></div>
-
-            <button id="spreadNone" class="secondaryToolbarButton spreadModeButtons spreadNone toggled" title="Do not join page spreads" tabindex="65" data-l10n-id="spread_none">
-              <span data-l10n-id="spread_none_label">No Spreads</span>
-            </button>
-            <button id="spreadOdd" class="secondaryToolbarButton spreadModeButtons spreadOdd" title="Join page spreads starting with odd-numbered pages" tabindex="66" data-l10n-id="spread_odd">
-              <span data-l10n-id="spread_odd_label">Odd Spreads</span>
-            </button>
-            <button id="spreadEven" class="secondaryToolbarButton spreadModeButtons spreadEven" title="Join page spreads starting with even-numbered pages" tabindex="67" data-l10n-id="spread_even">
-              <span data-l10n-id="spread_even_label">Even Spreads</span>
-            </button>
-
-            <div class="horizontalToolbarSeparator spreadModeButtons"></div>
-
-            <button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="68" data-l10n-id="document_properties">
-              <span data-l10n-id="document_properties_label">Document Properties…</span>
-            </button>
-          </div>
-        </div>  <!-- secondaryToolbar -->
-
-        <div class="toolbar">
-          <div id="toolbarContainer">
-            <div id="toolbarViewer">
-              <div id="toolbarViewerLeft">
-                <button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="11" data-l10n-id="toggle_sidebar" aria-expanded="false" aria-controls="sidebarContainer">
-                  <span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span>
-                </button>
-                <div class="toolbarButtonSpacer"></div>
-                <button id="viewFind" class="toolbarButton" title="Find in Document" tabindex="12" data-l10n-id="findbar" aria-expanded="false" aria-controls="findbar">
-                  <span data-l10n-id="findbar_label">Find</span>
-                </button>
-                <div class="splitToolbarButton hiddenSmallView">
-                  <button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="13" data-l10n-id="previous">
-                    <span data-l10n-id="previous_label">Previous</span>
-                  </button>
-                  <div class="splitToolbarButtonSeparator"></div>
-                  <button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="14" data-l10n-id="next">
-                    <span data-l10n-id="next_label">Next</span>
-                  </button>
-                </div>
-                <input type="number" id="pageNumber" class="toolbarField pageNumber" title="Page" value="1" size="4" min="1" tabindex="15" data-l10n-id="page" autocomplete="off">
-                <span id="numPages" class="toolbarLabel"></span>
-              </div>
-              <div id="toolbarViewerRight">
-                <button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView" title="Switch to Presentation Mode" tabindex="31" data-l10n-id="presentation_mode">
-                  <span data-l10n-id="presentation_mode_label">Presentation Mode</span>
-                </button>
-
-                <button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="32" data-l10n-id="open_file">
-                  <span data-l10n-id="open_file_label">Open</span>
-                </button>
-
-                <button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="33" data-l10n-id="print">
-                  <span data-l10n-id="print_label">Print</span>
-                </button>
-
-                <button id="download" class="toolbarButton download hiddenMediumView" title="Download" tabindex="34" data-l10n-id="download">
-                  <span data-l10n-id="download_label">Download</span>
-                </button>
-                <a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="35" data-l10n-id="bookmark">
-                  <span data-l10n-id="bookmark_label">Current View</span>
-                </a>
-
-                <div class="verticalToolbarSeparator hiddenSmallView"></div>
-
-                <button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36" data-l10n-id="tools" aria-expanded="false" aria-controls="secondaryToolbar">
-                  <span data-l10n-id="tools_label">Tools</span>
-                </button>
-              </div>
-              <div id="toolbarViewerMiddle">
-                <div class="splitToolbarButton">
-                  <button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21" data-l10n-id="zoom_out">
-                    <span data-l10n-id="zoom_out_label">Zoom Out</span>
-                  </button>
-                  <div class="splitToolbarButtonSeparator"></div>
-                  <button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22" data-l10n-id="zoom_in">
-                    <span data-l10n-id="zoom_in_label">Zoom In</span>
-                   </button>
-                </div>
-                <span id="scaleSelectContainer" class="dropdownToolbarButton">
-                  <select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
-                    <option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
-                    <option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
-                    <option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Page Fit</option>
-                    <option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Page Width</option>
-                    <option id="customScaleOption" title="" value="custom" disabled="disabled" hidden="true"></option>
-                    <option title="" value="0.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 50 }'>50%</option>
-                    <option title="" value="0.75" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 75 }'>75%</option>
-                    <option title="" value="1" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 100 }'>100%</option>
-                    <option title="" value="1.25" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 125 }'>125%</option>
-                    <option title="" value="1.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 150 }'>150%</option>
-                    <option title="" value="2" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 200 }'>200%</option>
-                    <option title="" value="3" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 300 }'>300%</option>
-                    <option title="" value="4" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 400 }'>400%</option>
-                  </select>
-                </span>
-              </div>
-            </div>
-            <div id="loadingBar">
-              <div class="progress">
-                <div class="glimmer">
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-
-        <div id="viewerContainer" tabindex="0">
-          <div id="viewer" class="pdfViewer"></div>
-        </div>
-
-        <div id="errorWrapper" hidden='true'>
-          <div id="errorMessageLeft">
-            <span id="errorMessage"></span>
-            <button id="errorShowMore" data-l10n-id="error_more_info">
-              More Information
-            </button>
-            <button id="errorShowLess" data-l10n-id="error_less_info" hidden='true'>
-              Less Information
-            </button>
-          </div>
-          <div id="errorMessageRight">
-            <button id="errorClose" data-l10n-id="error_close">
-              Close
-            </button>
-          </div>
-          <div class="clearBoth"></div>
-          <textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
-        </div>
-      </div> <!-- mainContainer -->
-
-      <div id="overlayContainer" class="hidden">
-        <div id="passwordOverlay" class="container hidden">
-          <div class="dialog">
-            <div class="row">
-              <p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p>
-            </div>
-            <div class="row">
-              <input type="password" id="password" class="toolbarField">
-            </div>
-            <div class="buttonRow">
-              <button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button>
-              <button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OK</span></button>
-            </div>
-          </div>
-        </div>
-        <div id="documentPropertiesOverlay" class="container hidden">
-          <div class="dialog">
-            <div class="row">
-              <span data-l10n-id="document_properties_file_name">File name:</span> <p id="fileNameField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_file_size">File size:</span> <p id="fileSizeField">-</p>
-            </div>
-            <div class="separator"></div>
-            <div class="row">
-              <span data-l10n-id="document_properties_title">Title:</span> <p id="titleField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_author">Author:</span> <p id="authorField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_subject">Subject:</span> <p id="subjectField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_keywords">Keywords:</span> <p id="keywordsField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_creation_date">Creation Date:</span> <p id="creationDateField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_modification_date">Modification Date:</span> <p id="modificationDateField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_creator">Creator:</span> <p id="creatorField">-</p>
-            </div>
-            <div class="separator"></div>
-            <div class="row">
-              <span data-l10n-id="document_properties_producer">PDF Producer:</span> <p id="producerField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_version">PDF Version:</span> <p id="versionField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_page_count">Page Count:</span> <p id="pageCountField">-</p>
-            </div>
-            <div class="row">
-              <span data-l10n-id="document_properties_page_size">Page Size:</span> <p id="pageSizeField">-</p>
-            </div>
-            <div class="separator"></div>
-            <div class="row">
-              <span data-l10n-id="document_properties_linearized">Fast Web View:</span> <p id="linearizedField">-</p>
-            </div>
-            <div class="buttonRow">
-              <button id="documentPropertiesClose" class="overlayButton"><span data-l10n-id="document_properties_close">Close</span></button>
-            </div>
-          </div>
-        </div>
-        <div id="printServiceOverlay" class="container hidden">
-          <div class="dialog">
-            <div class="row">
-              <span data-l10n-id="print_progress_message">Preparing document for printing…</span>
-            </div>
-            <div class="row">
-              <progress value="0" max="100"></progress>
-              <span data-l10n-id="print_progress_percent" data-l10n-args='{ "progress": 0 }' class="relative-progress">0%</span>
-            </div>
-            <div class="buttonRow">
-              <button id="printCancel" class="overlayButton"><span data-l10n-id="print_progress_close">Cancel</span></button>
-            </div>
-          </div>
-        </div>
-      </div>  <!-- overlayContainer -->
-
-    </div> <!-- outerContainer -->
-    <div id="printContainer"></div>
-  </body>
+	<head>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+		<meta name="google" content="notranslate">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge">
+		<title>PDF.js viewer</title>
+		<link rel="stylesheet" href="viewer.css">
+		<!-- This snippet is used in production (included from viewer.html) -->
+		<link rel="resource" type="application/l10n" href="locale/locale.properties">
+		<script src="../pdfBuild/pdf.js"></script>
+		<script src="viewer.js" charset="gb2312"></script>
+		<script>
+			var timestamp = new Date().getTime();
+			document.write('<link href="./index.css?v=' + timestamp + '" rel="stylesheet" type="text/css"/>')
+		</script>
+	</head>
+
+	<body tabindex="1">
+		<div id="outerContainer">
+
+			<div id="sidebarContainer">
+				<div id="toolbarSidebar">
+					<div id="toolbarSidebarLeft">
+						<div class="splitToolbarButton toggled">
+							<button id="viewThumbnail" class="toolbarButton toggled" title="Show Thumbnails"
+								tabindex="2" data-l10n-id="thumbs">
+								<span data-l10n-id="thumbs_label">Thumbnails</span>
+							</button>
+							<button id="viewOutline" class="toolbarButton"
+								title="Show Document Outline (double-click to expand/collapse all items)" tabindex="3"
+								data-l10n-id="document_outline">
+								<span data-l10n-id="document_outline_label">Document Outline</span>
+							</button>
+							<button id="viewAttachments" class="toolbarButton" title="Show Attachments" tabindex="4"
+								data-l10n-id="attachments">
+								<span data-l10n-id="attachments_label">Attachments</span>
+							</button>
+							<button id="viewLayers" class="toolbarButton"
+								title="Show Layers (double-click to reset all layers to the default state)" tabindex="5"
+								data-l10n-id="layers">
+								<span data-l10n-id="layers_label">Layers</span>
+							</button>
+						</div>
+					</div>
+
+					<div id="toolbarSidebarRight">
+						<div id="outlineOptionsContainer" class="hidden">
+							<div class="verticalToolbarSeparator"></div>
+
+							<button id="currentOutlineItem" class="toolbarButton" disabled="disabled"
+								title="Find Current Outline Item" tabindex="6" data-l10n-id="current_outline_item">
+								<span data-l10n-id="current_outline_item_label">Current Outline Item</span>
+							</button>
+						</div>
+					</div>
+				</div>
+				<div id="sidebarContent">
+					<div id="thumbnailView">
+					</div>
+					<div id="outlineView" class="hidden">
+					</div>
+					<div id="attachmentsView" class="hidden">
+					</div>
+					<div id="layersView" class="hidden">
+					</div>
+				</div>
+				<div id="sidebarResizer"></div>
+			</div> <!-- sidebarContainer -->
+
+			<div id="mainContainer">
+				<div class="findbar hidden doorHanger" id="findbar">
+					<div id="findbarInputContainer">
+						<input id="findInput" class="toolbarField" title="Find" placeholder="Find in document…"
+							tabindex="91" data-l10n-id="find_input">
+						<div class="splitToolbarButton">
+							<button id="findPrevious" class="toolbarButton findPrevious"
+								title="Find the previous occurrence of the phrase" tabindex="92"
+								data-l10n-id="find_previous">
+								<span data-l10n-id="find_previous_label">Previous</span>
+							</button>
+							<div class="splitToolbarButtonSeparator"></div>
+							<button id="findNext" class="toolbarButton findNext"
+								title="Find the next occurrence of the phrase" tabindex="93" data-l10n-id="find_next">
+								<span data-l10n-id="find_next_label">Next</span>
+							</button>
+						</div>
+					</div>
+
+					<div id="findbarOptionsOneContainer">
+						<input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94">
+						<label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight
+							all</label>
+						<input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
+						<label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match
+							case</label>
+					</div>
+					<div id="findbarOptionsTwoContainer">
+						<input type="checkbox" id="findEntireWord" class="toolbarField" tabindex="96">
+						<label for="findEntireWord" class="toolbarLabel" data-l10n-id="find_entire_word_label">Whole
+							words</label>
+						<span id="findResultsCount" class="toolbarLabel hidden"></span>
+					</div>
+
+					<div id="findbarMessageContainer">
+						<span id="findMsg" class="toolbarLabel"></span>
+					</div>
+				</div> <!-- findbar -->
+
+				<div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
+					<div id="secondaryToolbarButtonContainer">
+						<button id="secondaryPresentationMode"
+							class="secondaryToolbarButton presentationMode visibleLargeView"
+							title="Switch to Presentation Mode" tabindex="51" data-l10n-id="presentation_mode">
+							<span data-l10n-id="presentation_mode_label">Presentation Mode</span>
+						</button>
+
+						<button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView"
+							title="Open File" tabindex="52" data-l10n-id="open_file">
+							<span data-l10n-id="open_file_label">Open</span>
+						</button>
+
+						<button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print"
+							tabindex="53" data-l10n-id="print">
+							<span data-l10n-id="print_label">Print</span>
+						</button>
+
+						<button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView"
+							title="Download" tabindex="54" data-l10n-id="download">
+							<span data-l10n-id="download_label">Download</span>
+						</button>
+
+						<a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView"
+							title="Current view (copy or open in new window)" tabindex="55" data-l10n-id="bookmark">
+							<span data-l10n-id="bookmark_label">Current View</span>
+						</a>
+
+						<div class="horizontalToolbarSeparator visibleLargeView"></div>
+
+						<button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page"
+							tabindex="56" data-l10n-id="first_page">
+							<span data-l10n-id="first_page_label">Go to First Page</span>
+						</button>
+						<button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page"
+							tabindex="57" data-l10n-id="last_page">
+							<span data-l10n-id="last_page_label">Go to Last Page</span>
+						</button>
+
+						<div class="horizontalToolbarSeparator"></div>
+
+						<button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise"
+							tabindex="58" data-l10n-id="page_rotate_cw">
+							<span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
+						</button>
+						<button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw"
+							title="Rotate Counterclockwise" tabindex="59" data-l10n-id="page_rotate_ccw">
+							<span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
+						</button>
+
+						<div class="horizontalToolbarSeparator"></div>
+
+						<button id="cursorSelectTool" class="secondaryToolbarButton selectTool toggled"
+							title="Enable Text Selection Tool" tabindex="60" data-l10n-id="cursor_text_select_tool">
+							<span data-l10n-id="cursor_text_select_tool_label">Text Selection Tool</span>
+						</button>
+						<button id="cursorHandTool" class="secondaryToolbarButton handTool" title="Enable Hand Tool"
+							tabindex="61" data-l10n-id="cursor_hand_tool">
+							<span data-l10n-id="cursor_hand_tool_label">Hand Tool</span>
+						</button>
+
+						<div class="horizontalToolbarSeparator"></div>
+
+						<button id="scrollVertical"
+							class="secondaryToolbarButton scrollModeButtons scrollVertical toggled"
+							title="Use Vertical Scrolling" tabindex="62" data-l10n-id="scroll_vertical">
+							<span data-l10n-id="scroll_vertical_label">Vertical Scrolling</span>
+						</button>
+						<button id="scrollHorizontal" class="secondaryToolbarButton scrollModeButtons scrollHorizontal"
+							title="Use Horizontal Scrolling" tabindex="63" data-l10n-id="scroll_horizontal">
+							<span data-l10n-id="scroll_horizontal_label">Horizontal Scrolling</span>
+						</button>
+						<button id="scrollWrapped" class="secondaryToolbarButton scrollModeButtons scrollWrapped"
+							title="Use Wrapped Scrolling" tabindex="64" data-l10n-id="scroll_wrapped">
+							<span data-l10n-id="scroll_wrapped_label">Wrapped Scrolling</span>
+						</button>
+
+						<div class="horizontalToolbarSeparator scrollModeButtons"></div>
+
+						<button id="spreadNone" class="secondaryToolbarButton spreadModeButtons spreadNone toggled"
+							title="Do not join page spreads" tabindex="65" data-l10n-id="spread_none">
+							<span data-l10n-id="spread_none_label">No Spreads</span>
+						</button>
+						<button id="spreadOdd" class="secondaryToolbarButton spreadModeButtons spreadOdd"
+							title="Join page spreads starting with odd-numbered pages" tabindex="66"
+							data-l10n-id="spread_odd">
+							<span data-l10n-id="spread_odd_label">Odd Spreads</span>
+						</button>
+						<button id="spreadEven" class="secondaryToolbarButton spreadModeButtons spreadEven"
+							title="Join page spreads starting with even-numbered pages" tabindex="67"
+							data-l10n-id="spread_even">
+							<span data-l10n-id="spread_even_label">Even Spreads</span>
+						</button>
+
+						<div class="horizontalToolbarSeparator spreadModeButtons"></div>
+
+						<button id="documentProperties" class="secondaryToolbarButton documentProperties"
+							title="Document Properties…" tabindex="68" data-l10n-id="document_properties">
+							<span data-l10n-id="document_properties_label">Document Properties…</span>
+						</button>
+					</div>
+				</div> <!-- secondaryToolbar -->
+
+				<div class="toolbar">
+					<div id="toolbarContainer">
+						<div id="toolbarViewer">
+							<div id="toolbarViewerLeft">
+								<button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="11"
+									data-l10n-id="toggle_sidebar" aria-expanded="false"
+									aria-controls="sidebarContainer">
+									<span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span>
+								</button>
+								<div class="toolbarButtonSpacer"></div>
+								<button id="viewFind" class="toolbarButton" title="Find in Document" tabindex="12"
+									data-l10n-id="findbar" aria-expanded="false" aria-controls="findbar">
+									<span data-l10n-id="findbar_label">Find</span>
+								</button>
+								<div class="splitToolbarButton hiddenSmallView">
+									<button class="toolbarButton pageUp" title="Previous Page" id="previous"
+										tabindex="13" data-l10n-id="previous">
+										<span data-l10n-id="previous_label">Previous</span>
+									</button>
+									<div class="splitToolbarButtonSeparator"></div>
+									<button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="14"
+										data-l10n-id="next">
+										<span data-l10n-id="next_label">Next</span>
+									</button>
+								</div>
+								<input type="number" id="pageNumber" class="toolbarField pageNumber" title="Page"
+									value="1" size="4" min="1" tabindex="15" data-l10n-id="page" autocomplete="off">
+								<span id="numPages" class="toolbarLabel"></span>
+							</div>
+							<div id="toolbarViewerRight">
+								<button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView"
+									title="Switch to Presentation Mode" tabindex="31" data-l10n-id="presentation_mode">
+									<span data-l10n-id="presentation_mode_label">Presentation Mode</span>
+								</button>
+
+								<button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File"
+									tabindex="32" data-l10n-id="open_file">
+									<span data-l10n-id="open_file_label">Open</span>
+								</button>
+
+								<button id="print" class="toolbarButton print hiddenMediumView" title="Print"
+									tabindex="33" data-l10n-id="print">
+									<span data-l10n-id="print_label">Print</span>
+								</button>
+
+								<button id="download" class="toolbarButton download hiddenMediumView" title="Download"
+									tabindex="34" data-l10n-id="download">
+									<span data-l10n-id="download_label">Download</span>
+								</button>
+								<a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView"
+									title="Current view (copy or open in new window)" tabindex="35"
+									data-l10n-id="bookmark">
+									<span data-l10n-id="bookmark_label">Current View</span>
+								</a>
+
+								<div class="verticalToolbarSeparator hiddenSmallView"></div>
+
+								<button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36"
+									data-l10n-id="tools" aria-expanded="false" aria-controls="secondaryToolbar">
+									<span data-l10n-id="tools_label">Tools</span>
+								</button>
+							</div>
+							<div id="toolbarViewerMiddle">
+								<div class="splitToolbarButton">
+									<button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21"
+										data-l10n-id="zoom_out">
+										<span data-l10n-id="zoom_out_label">Zoom Out</span>
+									</button>
+									<div class="splitToolbarButtonSeparator"></div>
+									<button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22"
+										data-l10n-id="zoom_in">
+										<span data-l10n-id="zoom_in_label">Zoom In</span>
+									</button>
+								</div>
+								<span id="scaleSelectContainer" class="dropdownToolbarButton">
+									<select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
+										<option id="pageAutoOption" title="" value="auto" selected="selected"
+											data-l10n-id="page_scale_auto">Automatic Zoom</option>
+										<option id="pageActualOption" title="" value="page-actual"
+											data-l10n-id="page_scale_actual">Actual Size</option>
+										<option id="pageFitOption" title="" value="page-fit"
+											data-l10n-id="page_scale_fit">Page Fit</option>
+										<option id="pageWidthOption" title="" value="page-width"
+											data-l10n-id="page_scale_width">Page Width</option>
+										<option id="customScaleOption" title="" value="custom" disabled="disabled"
+											hidden="true"></option>
+										<option title="" value="0.5" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 50 }'>50%</option>
+										<option title="" value="0.75" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 75 }'>75%</option>
+										<option title="" value="1" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 100 }'>100%</option>
+										<option title="" value="1.25" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 125 }'>125%</option>
+										<option title="" value="1.5" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 150 }'>150%</option>
+										<option title="" value="2" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 200 }'>200%</option>
+										<option title="" value="3" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 300 }'>300%</option>
+										<option title="" value="4" data-l10n-id="page_scale_percent"
+											data-l10n-args='{ "scale": 400 }'>400%</option>
+									</select>
+								</span>
+							</div>
+						</div>
+						<div id="loadingBar">
+							<div class="progress">
+								<div class="glimmer">
+								</div>
+							</div>
+						</div>
+					</div>
+				</div>
+
+				<div id="viewerContainer" tabindex="0">
+					<div id="viewer" class="pdfViewer"></div>
+				</div>
+
+				<div id="errorWrapper" hidden='true'>
+					<div id="errorMessageLeft">
+						<span id="errorMessage"></span>
+						<button id="errorShowMore" data-l10n-id="error_more_info">
+							More Information
+						</button>
+						<button id="errorShowLess" data-l10n-id="error_less_info" hidden='true'>
+							Less Information
+						</button>
+					</div>
+					<div id="errorMessageRight">
+						<button id="errorClose" data-l10n-id="error_close">
+							Close
+						</button>
+					</div>
+					<div class="clearBoth"></div>
+					<textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea>
+				</div>
+			</div> <!-- mainContainer -->
+
+			<div id="overlayContainer" class="hidden">
+				<div id="passwordOverlay" class="container hidden">
+					<div class="dialog">
+						<div class="row">
+							<p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:
+							</p>
+						</div>
+						<div class="row">
+							<input type="password" id="password" class="toolbarField">
+						</div>
+						<div class="buttonRow">
+							<button id="passwordCancel" class="overlayButton"><span
+									data-l10n-id="password_cancel">Cancel</span></button>
+							<button id="passwordSubmit" class="overlayButton"><span
+									data-l10n-id="password_ok">OK</span></button>
+						</div>
+					</div>
+				</div>
+				<div id="documentPropertiesOverlay" class="container hidden">
+					<div class="dialog">
+						<div class="row">
+							<span data-l10n-id="document_properties_file_name">File name:</span>
+							<p id="fileNameField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_file_size">File size:</span>
+							<p id="fileSizeField">-</p>
+						</div>
+						<div class="separator"></div>
+						<div class="row">
+							<span data-l10n-id="document_properties_title">Title:</span>
+							<p id="titleField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_author">Author:</span>
+							<p id="authorField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_subject">Subject:</span>
+							<p id="subjectField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_keywords">Keywords:</span>
+							<p id="keywordsField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_creation_date">Creation Date:</span>
+							<p id="creationDateField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_modification_date">Modification Date:</span>
+							<p id="modificationDateField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_creator">Creator:</span>
+							<p id="creatorField">-</p>
+						</div>
+						<div class="separator"></div>
+						<div class="row">
+							<span data-l10n-id="document_properties_producer">PDF Producer:</span>
+							<p id="producerField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_version">PDF Version:</span>
+							<p id="versionField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_page_count">Page Count:</span>
+							<p id="pageCountField">-</p>
+						</div>
+						<div class="row">
+							<span data-l10n-id="document_properties_page_size">Page Size:</span>
+							<p id="pageSizeField">-</p>
+						</div>
+						<div class="separator"></div>
+						<div class="row">
+							<span data-l10n-id="document_properties_linearized">Fast Web View:</span>
+							<p id="linearizedField">-</p>
+						</div>
+						<div class="buttonRow">
+							<button id="documentPropertiesClose" class="overlayButton"><span
+									data-l10n-id="document_properties_close">Close</span></button>
+						</div>
+					</div>
+				</div>
+				<div id="printServiceOverlay" class="container hidden">
+					<div class="dialog">
+						<div class="row">
+							<span data-l10n-id="print_progress_message">Preparing document for printing…</span>
+						</div>
+						<div class="row">
+							<progress value="0" max="100"></progress>
+							<span data-l10n-id="print_progress_percent" data-l10n-args='{ "progress": 0 }'
+								class="relative-progress">0%</span>
+						</div>
+						<div class="buttonRow">
+							<button id="printCancel" class="overlayButton"><span
+									data-l10n-id="print_progress_close">Cancel</span></button>
+						</div>
+					</div>
+				</div>
+			</div> <!-- overlayContainer -->
+
+		</div> <!-- outerContainer -->
+		<div id="printContainer"></div>
+	</body>
 </html>

+ 36 - 41
TEAMModelOS/ClientApp/src/api/http.js

@@ -16,23 +16,23 @@ const NO_ACCESS_API = [
     '/common/study/sign-in',
     'third/sso/opt-tmdid-bind',
     '/sc/bind',
-	'/core/get-short-url',
-	'/core/get-long-url'
+    '/core/get-short-url',
+    '/core/get-long-url'
 ]
 // 需要携带access_token 不需要携带auth-token
 const NO_AUTH_API = [
     '/teacher/init/get-teacher-info',
     '/teacher/init/get-school-info',
     '/grouplist/scan-code-join-list',
-	'/tmduser/init/get-tmduser-info',
-	'/student/get-student-info',
+    '/tmduser/init/get-tmduser-info',
+    '/student/get-student-info',
     '/teacher/init/GetUserInfo',
-	'/core/get-short-url',
-	'/core/get-long-url'
+    '/core/get-short-url',
+    '/core/get-long-url'
 ]
 // 不进行错误提示白名单
 const NO_WARNING = [
-	'http://localhost:59995/'
+    'http://localhost:59995/'
 ]
 
 let refreshing = false
@@ -55,7 +55,7 @@ axios.interceptors.request.use(
             }
         }
         if (!isNeedAccess) return config
-		
+
         /**
          * 登录之后,获取auth_token之前
          * 1、检查用户操作时间 
@@ -66,7 +66,7 @@ axios.interceptors.request.use(
         if (webEndTime && time_now > webEndTime) {
             console.log('长时间未操作,重新登录', config)
             loginOut()
-            localStorage.setItem('loginOut','长时间未操作')
+            sessionStorage.setItem('loginOut', '长时间未操作,重新登录')
             return
         }
         let access_token = localStorage.getItem('access_token')
@@ -76,7 +76,18 @@ axios.interceptors.request.use(
             let flag = checkToken()
             if (flag && !refreshing) {
                 console.log('token即将过期,刷新token')
-                await refreshToken()
+                try {
+                    refreshing = true
+                    let freshRes = await refreshToken()
+                    localStorage.setItem("access_token", freshRes.data.access_token)
+                    localStorage.setItem("expires_in", freshRes.data.expires_in)
+                    refreshing = false
+                } catch (e) {
+                    refreshing = false
+                    loginOut()
+                    sessionStorage.setItem('loginOut', 'token刷新失败,退出重新登录')
+                }
+
             }
             config.headers['Authorization'] = 'Bearer ' + localStorage.getItem('access_token')
         }
@@ -97,12 +108,12 @@ axios.interceptors.request.use(
          * 获取auth_token之后的API
          * 1、检查auth_token是否存在
          */
-		let identity = sessionStorage.getItem('identity')
+        let identity = sessionStorage.getItem('identity')
         let auth_token = identity === 'student' ? localStorage.getItem('stu_auth_token') : localStorage.getItem('auth_token')
         if (!auth_token) {
             console.log('auth_token失败', config)
             loginOut()
-            localStorage.setItem('loginOut','auth_token失败')
+            sessionStorage.setItem('loginOut', 'localStorage没有auth_token:auth_token失败,重新登录')
             return
         }
         //通过验证设置对应参数
@@ -123,26 +134,24 @@ axios.interceptors.response.use(
                 querry: { redirect: router.currentRoute.fullPath }// 从哪个页面跳转
             })
         }
-		// 保存最新的服务器端时间
-		if(response.headers.date){
-			localStorage.setItem('serverTime', new Date(response.headers.date).getTime())
-		}
+        // 保存最新的服务器端时间
+        if (response.headers.date) {
+            localStorage.setItem('serverTime', new Date(response.headers.date).getTime())
+        }
         // API 呼叫完成後以現在的時間向後加四小時 四小时没有操作过则需要重新登录
-        // if (isProduction) {
         let endTime = (new Date().getTime() + (4 * 60 * 60 * 1000))
         localStorage.setItem('webEndTime', endTime)
-        // }
-
         return response
     },
     error => {
-		if(!error.response){
-			if(!NO_WARNING.includes(error.config.url)){
-				Message.error(app.$t('http.error'))
-			}
-		}else if (error.response && error.response.status === 401) {
+        if (!error.response) {
+            if (!NO_WARNING.includes(error.config.url)) {
+                Message.error(app.$t('http.error'))
+            }
+        } else if (error.response && error.response.status === 401) {
             localStorage.clear()
             window.location.href = window.location.origin + '/login'
+            sessionStorage.setItem('loginOut', error.config.url + ':API401,重新登录')
             Message.error(app.$t('http.error401'))
         } else if (error.response.status === 500) {
             Message.error(app.$t('http.error500'))
@@ -174,28 +183,14 @@ function checkToken() {
 }
 
 /**刷新token */
-async function refreshToken() {
-    refreshing = true
+function refreshToken() {
     let srvAdr = localStorage.getItem('srvAdr')
     let url = config.state[srvAdr].coreAPIUrl
-
-    await axios.post(url + '/oauth2/token', {
+    return axios.post(url + '/oauth2/token', {
         "grant_type": "refresh_token",
         'client_id': config.state[srvAdr].clientID,
         "access_token": localStorage.getItem('access_token')
-    }).then(
-        res => {
-            localStorage.setItem("access_token", res.data.access_token)
-            localStorage.setItem("expires_in", res.data.expires_in)
-            refreshing = false
-        },
-        err => {
-            refreshing = false
-            console.log('token刷新失败,退出重新登录')
-            loginOut()
-            localStorage.setItem('loginOut','refreshToken')
-        }
-    )
+    })
 }
 
 // 超时退出重新登录

+ 5 - 1
TEAMModelOS/ClientApp/src/api/studentWeb.js

@@ -311,10 +311,14 @@ export default {
     getStuInfo: function(data) {
         return post("/student/student-manage", data)
     },
-
+    // 课堂记录列表
     getClassRecord: function(data) {
         return post("/common/lesson-record/get-lesson-record", data)
     },
+    // 课堂记录数量
+    getRecordNum: function(data) {
+        return post("/common/lesson-record/get-lesson-record-count", data)
+    },
 
     getTeacherName: function(data) {
         return post("/tmduser/init/get-tmd-info", data)

+ 17 - 0
TEAMModelOS/ClientApp/src/assets/student-web/component_styles/course-content.less

@@ -88,6 +88,7 @@
             width: 100%;
             border-bottom: 1px solid rgba(0, 0, 0, 0.1);
             padding: 15px 10px 15px 15px;
+            position: relative;
 
             &:hover {
                 background: linear-gradient(-0.75turn, #fafafa, #d4ede1);
@@ -98,6 +99,7 @@
             .list-item-info {
                 padding-right: 20px;
                 position: relative;
+                display: flex;
 
                 .list-item-title {
                     font-weight: bolder;
@@ -110,6 +112,21 @@
                     }
                 }
             }
+
+            .record-poster-wrap{
+                width: 120px;
+                height: 65px;
+                background-size: contain;
+                background-repeat: no-repeat;
+                background-position: center;
+                margin-right: 20px;
+            }
+
+            .upload {
+                position: absolute;
+                top: 40%;
+                right: 20px;
+            }
         }
 
         .list-item-selected {

+ 0 - 1
TEAMModelOS/ClientApp/src/components/public/frontEndMain/Index.vue

@@ -169,7 +169,6 @@ export default {
         let cur = hostList.find(item => {
             return host.includes(item.host)
         })
-        console.log('这里', cur, this.$route)
         if (cur && this.$route.name == 'login') {
             this.isShowTMD = cur.isShowTMD
             this.$router.push({

+ 2 - 2
TEAMModelOS/ClientApp/src/components/research-dashboard/LeftTop.vue

@@ -105,8 +105,8 @@
 			.item {
 				width: 18.2%;
 				border-radius: 6px;
-				padding:8px;
-				margin: 8px;
+				padding: 8px;
+				margin: 0.3% 0.9% 1.3% 0.9%;
 
 				.count-num {
 					display: inline-block;

+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.vue

@@ -534,7 +534,7 @@ export default {
                 // sasInfo.name = this.recordInfo.scope ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
                 // sasInfo.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(sasInfo.name) - 1)
                 let sasInfo = await this.$tools.getBlobSas(this.recordInfo.scope === 'school' ? this.recordInfo.school : this.recordInfo.tmdid)
-                eNote = `${sasInfo.url}/${sasInfo.name}/records/${this.recordInfo.id}/Note.pdf${sasInfo.sas}`
+                eNote = `${sasInfo.url}/${sasInfo.name}/records/${this.recordInfo.id}/Note.pdf?${sasInfo.sas}`
             }
             window.open('/web/viewer.html?file=' + encodeURIComponent(eNote))
             // if (this.recordInfo.eNote) {

+ 24 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReport.vue

@@ -76,6 +76,11 @@
                         <LessonTestReportCharts :chartsData="chartsData"></LessonTestReportCharts>
                     <!-- </Card> -->
                 </i-col>
+                <i-col :xs="24" :sm="24" :md="24" :lg="24">
+                    <Card style="margin-top: 20px;">
+                        <QuCount :quData="quDataSub" />
+                    </Card>
+                </i-col>
             </Row>
         </div>
         <div class="QAsheet" v-if="testState != 1">
@@ -387,6 +392,7 @@
 <script>
     import pdf from 'vue-pdf'
     import LessonTestReportCharts from "./LessonTestReportCharts/LessonTestReportCharts";
+    import QuCount from './LessonTestReportCharts/QuCount.vue';
     import SubjectMould from './SubjectMould.vue';
     import Loading from "vue-loading-overlay";
     import "vue-loading-overlay/dist/vue-loading.css";
@@ -395,6 +401,7 @@
         name: "LessonTestReport",
         components: {
             LessonTestReportCharts,
+            QuCount,
             SubjectMould,
             Loading,
             pdf
@@ -423,6 +430,12 @@
                 default: () => {
                     return 0
                 }
+            },
+            quData: {
+                type: Object,
+                default: () => {
+                    return undefined
+                }
             }
         },
         data() {
@@ -476,6 +489,7 @@
                 previewFile: null,
                 CarouselIndex: 0,
                 imgList: [],
+                quDataSub: [],
             };
         },
         mounted() {
@@ -639,6 +653,7 @@
                 this.newPaperData.length = 0
                 this.ansData.length = 0
                 this.markData.length = 0
+                this.quDataSub.length = 0
                 let exam = this.getPaperInfo.item ? [...this.getPaperInfo.item] : []
                 if (exam.length) {
                     this.ansData = await this.getItem(this.examInfo.stuAns[0])
@@ -719,6 +734,15 @@
                         }
                     })
                 }
+                let subjectId = this.getItemTitle.owner === 'school' ? this.paperInfo.subjectId : this.examInfo.subject.id
+                let indexQ = this.quData ? this.quData.subjects.findIndex(item => item.id === subjectId) : -1
+                if(indexQ != -1) {
+                    this.quDataSub = this.quData.data[indexQ]
+                    paper.forEach((item, index) => {
+                        this.quDataSub[index].quLabel = item.paperIndex
+                        this.quDataSub[index].type = item.getScore === item.score
+                    })
+                }
                 this.paperData = [...paper]
                 this.showPaperData = [...this.paperData]
                 if (this.paperData.length) {

+ 281 - 0
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/QuCount.vue

@@ -0,0 +1,281 @@
+<template>
+    <div>
+        <div class="qu-score-count" id="class-score-count"></div>
+        <p class="legend-info">
+            <span>{{ $t('studentWeb.exam.chart.legendSimple.legend1') }}</span>
+            <span>{{ $t('studentWeb.exam.chart.legendSimple.legend2') }}√</span>
+            <span>{{ $t('studentWeb.exam.chart.legendSimple.legend3') }}×</span>
+        </p>
+    </div>
+</template>
+<script>
+import elementResizeDetectorMaker from "element-resize-detector"
+export default {
+    props: {
+        quData: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        }
+    },
+    data() {
+        let _this = this
+        return {
+            isShowRate: true,
+            progressPie: undefined,
+            stuCount: 0,
+            option: {}
+        }
+    },
+    created() {
+    },
+    mounted() {
+        this.progressPie = this.$echarts.init(document.getElementById('class-score-count'), 'macarons')
+        this.progressPie.setOption(this.option)
+        let erd11 = elementResizeDetectorMaker()
+        erd11.listenTo(document.getElementById("class-score-count"), () => {
+            this.$nextTick(() => {
+                //监听到事件后执行的业务逻辑
+                this.progressPie.resize()
+            })
+        })
+    },
+    watch: {
+        quData: {
+            handler(n, o) {
+                let _this = this
+                this.$nextTick(() => {
+                    if (this.quData.length) _this.stuCount = this.quData[0].correct + this.quData[0].wrong
+                    this.option = {
+                        tooltip: {
+                            trigger: 'item',
+                            formatter: '{b} : {c}' + this.$t('unit.text7')
+                        },
+                        title: {
+                            "text": this.$t('learnActivity.simple.quCorrectRate'),
+                            "left": "center",
+                            "top": 0,
+                            "textStyle": {
+                                fontSize: 15,
+                                color: "#333"
+                            }
+                        },
+                        legend: {
+                            /* itemStyle: {
+                                opacity: 0
+                            }, */
+                            /* formatter: (params) => {
+                                return `√表示答对`
+                            }, */
+                            bottom: 0,
+                        },
+                        tooltip: {
+                            formatter: (params) => {
+                                return `${_this.$t('learnActivity.simple.rac')} ${params.data.value.toFixed(0)}%(${_this.quData[params.dataIndex].correct}${_this.$t('unit.text7')})`
+                            }
+                        },
+                        grid: {
+                            // width: "100%",
+                            left: 50,
+                            right: 50
+                        },
+                        xAxis: {
+                            show: true,
+                            // name:'题号',
+                            nameLocation: 'end',
+                            type: 'category',
+                            data: [],
+                            axisLine: {
+                                lineStyle: {
+                                    color: "#AAA"
+                                }
+                            },
+                            axisLabel: {
+                                rotate: 0
+                            }
+                        },
+                        yAxis: {
+                            // name:'正确率',
+                            type: 'value',
+                            axisLine: {
+                                lineStyle: {
+                                    color: "#AAA"
+                                }
+                            },
+                        },
+                        series: [
+                            {
+                                data: [],
+                                type: 'bar',
+                                barMinWidth: 30,
+                                barMaxWidth: 30,
+                                label: {
+                                    show: true,
+                                    position: 'top',
+                                    formatter: (params) => {
+                                        //统计人数的算法
+                                        // if (_this.stuCount > 0) {
+                                        //     return `${(params.data * 100 / _this.stuCount).toFixed(1)}%`
+                                        // } else {
+                                        //     return params.data
+                                        // }
+                                        // console.log(params);
+                                        // 统计正确率的算法
+                                        return _this.isShowRate ? `${params.data.type ? '{typea|√}' : '{typeb|×}'}\n{count|${params.data.value.toFixed(0)}%}` : ''
+                                    },
+                                    rich: {
+                                        typea: {
+                                            color: '#00AD6C',
+                                            fontSize: 20,
+                                            // height: 24,
+                                            // padding: [0, 5, 0, 5],
+                                            align: 'center'
+                                        },
+                                        typeb: {
+                                            color: '#FF5508',
+                                            fontSize: 20,
+                                            // height: 24,
+                                            // padding: [0, 5, 0, 5],
+                                            align: 'center'
+                                        },
+                                        count: {
+                                            color: '#333',
+                                            height: 24,
+                                            // padding: [0, 5, 0, 5],
+                                            // align: 'right'
+                                        },
+                                    },
+                                },
+                                itemStyle: {
+                                    normal: {
+                                        color: function (params) {
+                                            const colorList = ['#ed4014', '#ff9900', '#19be6b']
+                                            //统计人数的算法
+                                            // if (_this.stuCount >= 0) {
+                                            //     let rate = params.data * 100 / _this.stuCount
+                                            //     console.log(params, rate)
+                                            //     if (rate >= 70) {
+                                            //         return colorList[2]
+                                            //     } else if (rate > 50) {
+                                            //         return colorList[1]
+                                            //     } else {
+                                            //         return colorList[0]
+                                            //     }
+                                            // } else {
+                                            //     return colorList[2]
+                                            // }
+                                            // 统计正确率的算法
+                                            if (params.data.value >= 70) {
+                                                return colorList[2]
+                                            } else if (params.data.value > 50) {
+                                                return colorList[1]
+                                            } else {
+                                                return colorList[0]
+                                            }
+
+                                        }
+                                    }
+                                },
+                                stillShowZeroSum: true,
+                            },
+                        ]
+                    }
+                    if (!this.progressPie) {
+                        this.progressPie = this.$echarts.init(document.getElementById('class-score-count'), 'macarons')
+                    }
+                    this.option.series[0].data = this.quData.map(item => {
+                        return {
+                            value: item.correct * 100 / this.stuCount,
+                            type: item.type
+                        }
+                    })
+                    /* this.option.series[0].data = [
+                        {
+                            value: this.quData.map(item => item.correct * 100 / this.stuCount)
+                        },
+                        {
+                            value: this.quData.map(item => {return item.type})
+                        }
+                    ] */
+                    // this.option.series[0].data = this.quData.map(item => item.correct * 100 / this.stuCount) //计算正确率
+                    this.option.xAxis.data = this.quData.map(item => item.quLabel)
+                    // if (this.quData.length) this.option.yAxis.max = this.quData[0].correct + this.quData[0].wrong
+                    if (this.quData.length) this.option.yAxis.max = 100 //计算比例不算人数
+                    if (this.quData.length > 20) {
+                        this.option.dataZoom = [
+                            {
+                                show: true,
+                                height: 8,
+                                xAxisIndex: [
+                                    0
+                                ],
+                                bottom: 10,
+                                endValue: 30,
+                                startValue: 0,
+                                handleIcon: 'M512 497.821538m-418.264615 0a418.264615 418.264615 0 1 0 836.52923 0 418.264615 418.264615 0 1 0-836.52923 0Z',
+                                handleSize: '100%',
+                                handleStyle: {
+                                    color: '#d3dee5'
+
+                                },
+                                textStyle: {
+                                    color: '#fff'
+                                },
+                                borderRadius: '5px',
+                                maxValue: 30,
+                            },
+                            {
+                                type: 'inside',
+                                show: true,
+                                height: 15,
+                                endValue: 30,
+                                startValue: 0,
+                                maxValue: 30,
+                            }
+                        ]
+                    } else {
+                        this.option.dataZoom = []
+                    }
+                    this.progressPie.setOption(this.option, true)
+                    /* this.progressPie.on('datazoom', (params) => {
+                        let start = params.batch[0]?.start
+                        let end = params.batch[0]?.end
+                        if (end - start > 30) {
+                            this.isShowRate = false
+                        } else {
+                            this.isShowRate = true
+                        }
+                    }) */
+                })
+            },
+            deep: true,
+            immediate: true
+        },
+        /* quData: {
+            handler(n, o) {
+                if (n) {
+                    this.$nextTick(() => {
+                        this.getFiled()
+                        this.setMap()
+                    })
+                }
+            }
+        } */
+    }
+}
+</script>
+<style scoped lang="less">
+.qu-score-count {
+    width: 100%;
+    height: 280px;
+}
+.legend-info {
+    text-align: center;
+    font-weight: bold;
+
+    & > span:not(:last-child) {
+        margin-right: 10px;
+    }
+}
+</style>

+ 12 - 1
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/LessonTestReportCharts/ScoreBarChart.vue

@@ -1,6 +1,10 @@
 <template>
     <div class="score-bar-chart">
         <!-- <h4>{{ $t("studentWeb.exam.chart.scoreDistribution") }}</h4> -->
+        
+        <div class="no-data">
+            <p class="no-data-title">{{ $t("studentWeb.exam.chart.scoreDistribution") }}</p>
+        </div>
         <div class="attendance">
             {{ $t("studentWeb.exam.chart.participant") }}
             <span class="timeNum">{{ Attendance }}</span><!--  / {{ Attendance }} -->
@@ -47,7 +51,8 @@ export default {
                     textStyle: {
                         // fontWeight: "normal",
                         fontSize: "14",
-                    }
+                    },
+                    show: false,
                 },
                 tooltip: {
                     trigger: "item",
@@ -128,6 +133,12 @@ export default {
     height: 420px;
     color: rgba(0, 0, 0, 0.726);
 }
+
+.score-bar-chart .no-data .no-data-title {
+    color: #484848;
+    font-weight: bolder;
+}
+
 .attendance {
     position: relative;
     top: 10px;

+ 40 - 2
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperView.vue

@@ -48,7 +48,7 @@
                             <div v-if="chooseData.subject !== undefined">
                                 <!-- <div class="title-rect" /> -->
                                 <!-- <h2 class="title-rect-name">{{$t("studentWeb.exam.subjectNow")}}:{{chooseData.subject.name}}</h2> -->
-                                <LessonTestReport :paperInfo="selectData" :examInfo="chooseData" :chartsData="chartsData" :average="average[activeIndex]" />
+                                <LessonTestReport :paperInfo="selectData" :examInfo="chooseData" :chartsData="chartsData" :average="average[activeIndex]" :quData="quData" />
                             </div>
                         </div>
                     </TabPane>
@@ -113,7 +113,8 @@
                 activeIndex: null, //当前科目的下标
                 chartsData: undefined, //单科知识点、认知层次等
                 allCharts: undefined, //知识点、认知层次等
-                average: [], //班级平均分
+                average: [], //班级平均分,
+                quData: undefined,
             };
         },
         methods: {
@@ -147,6 +148,7 @@
                                     knowledge: res.knowledge,
                                     total: res.total
                                 }
+                                this.getCorrectData(res)
                                 res.papers.forEach(item => {
                                     if (item.scope) {
                                         item.source = null
@@ -213,6 +215,42 @@
                 }
                 this.isLoad = false
             },
+            //获取各科题目正确率数据
+            getCorrectData(data) {
+                let d = []
+                let totalNum = 0
+                // 不同科目,多个班级,以科目的数量为准
+                data.total.forEach((item, index) => {
+                    if((index + 1) % data.subjects.length === 0) {
+                        item.forEach(num => {
+                            totalNum += num
+                        })
+                    }
+                })
+                // if (data.averageTotal) {
+                    data.wno.forEach(item => {
+                        let total = totalNum //总人数
+                        let cData = item.map((w, i) => {
+                            let correct = total - w
+                            return {
+                                correct: correct, //正确人数
+                                wrong: w,//错误人数
+                                rate: total ? parseInt(correct * 100 / total) : 0,//正确率
+                                quLabel: i,
+                                type: false,
+                            }
+                        })
+                        d.push(cData)
+                    })
+                    this.quData = {
+                        subjects: data.subjects,
+                        data: d
+                    }
+                    // this.correctData = d
+                /* } else {
+                    this.correctData = []
+                } */
+            },
             // 删除不存在的问卷
             delActivity() {
                 let roles = ""

+ 104 - 29
TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseListView.vue

@@ -271,7 +271,7 @@
                         </Panel>
                     </Collapse>
                 </TabPane> -->
-                <TabPane :label="$t('studentWeb.courseContent.classRecord')" name="tab5">
+                <TabPane :label="$t('studentWeb.courseContent.classRecord') + '(' + recordNum + ')'" name="tab5">
                         <div class="list-block-box">
                             <template v-if="recordList.length">
                                 <!-- <vuescroll> -->
@@ -283,15 +283,21 @@
                                                 <svg-icon icon-class="hiteach" />
                                             </li> -->
                                             <li class="list-item-info">
-                                                <p class="list-item-title">
-                                                    <span>{{ item.name }}</span>
-                                                    <!-- <span style="margin-left: 20px">老师:{{ item.teacher }}</span> -->
-                                                </p>
-                                                <p class="list-item-time">
-                                                    <span>{{ item.startTime }}</span>
-                                                    <span>{{ $t('studentWeb.baseInfo.duration') }}:{{ item.time }}</span>
-                                                </p>
+                                                <RcdPoster class="record-poster-wrap" :poster="item.CoverImage"></RcdPoster>
+                                                <div>
+                                                    <p class="list-item-title">
+                                                        <span>{{ item.name }}</span>
+                                                        <!-- <span style="margin-left: 20px">老师:{{ item.teacher }}</span> -->
+                                                    </p>
+                                                    <p class="list-item-time">
+                                                        <span>{{ item.startTime }}</span>
+                                                        <span>{{ $t('studentWeb.baseInfo.duration') }}:{{ item.time }}</span>
+                                                    </p>
+                                                </div>
                                             </li>
+                                            <span class="upload" @click.capture.stop="uploadNote(item)">
+                                                <Icon type="md-download" size="16" />
+                                            </span>
                                         </ul>
                                     </div>
                                 </Scroll>
@@ -321,10 +327,16 @@
                     <SchoolReport :classInfo="courseNow" />
                 </TabPane> -->
                 <!-- 同学名单 -->
-                <TabPane :label="$t('studentWeb.courseContent.classmates')" name="tab3">
+                <TabPane :label="$t('studentWeb.courseContent.classmates') + '(' + stuTotal + ')'" name="tab3">
+                    <div style="margin-bottom: 10px;">
+                        {{ $t("studentWeb.exam.studentScore.class") }}:
+                        <Select v-model="courseIndex" style="width:200px">
+                            <Option v-for="(item, index) in classList" :value="index" :key="index">{{ item.name }}</Option>
+                        </Select>
+                    </div>
                     <div v-if="isChangeGroupView == false">
                         <!-- <vuescroll> -->
-                            <Table :columns="stuCol" :data="stuList" :height="650"></Table>
+                            <Table :columns="stuCol" :data="stuList[courseIndex]" :height="650"></Table>
                         <!-- </vuescroll> -->
                     </div>
                     <!--小組模式-->
@@ -381,7 +393,7 @@
             <Tabs v-model="list">
                 <TabPane :label="$t('studentWeb.courseContent.classmates')" name="stuList">
                     <div v-show="!isChangeGroupView">
-                        <Table :columns="stuCol" :data="stuList">
+                        <Table :columns="stuCol" :data="stuList[courseIndex]">
                             <template slot-scope="{ row }" slot="no">
                                 <p :class="{'my-name': row.id == userInfo.sub}">
                                     {{row.no}}
@@ -534,6 +546,7 @@ import ClassRecord from './../ClassRecord/ClassRecord';
 import { mapGetters, mapState } from 'vuex';
 import ActivityView from './CourseView/ActivityView.vue';
 import SchoolReport from "./CourseView/SchoolReport";
+import RcdPoster from '../../../view/homepage/RcdPoster.vue';
 
 export default {
     name: "CourseListView",
@@ -542,6 +555,7 @@ export default {
         ClassRecord,
         ActivityView,
         SchoolReport,
+        RcdPoster,
     },
     data(vm) {
         return {
@@ -665,6 +679,11 @@ export default {
             needParam: undefined,
             showFixList: [],
             continuationToken: null,
+            sasInfo: undefined,
+            courseIndex: 0,
+            stuTotal: 0, //学生总人数
+            recordNum: 0, //课堂记录总数
+            classList: [],
         };
     },
 
@@ -692,22 +711,28 @@ export default {
         // 查找学生信息(标准)
         findStuInfor(course, haveClass) {
             this.stuGroup = []
-            this.stuList = []
+            // this.stuList = []
             let req = {
-                ids: []
+                ids: [course]
             }
             // 行政班才传schoolId
             if(haveClass) {
-                req.ids = course.classId
-                req.schoolId = course.school
-            } else {
-                req.ids = course.stuList
-            }
+                // req.ids = course
+                req.schoolId = this.courseNow.school
+            }/*  else {
+                req.ids = course
+            } */
             this.$api.common.getGroupListByIds(req).then(res => {
+                if(res.groups.length) {
+                    res.groups.forEach(groups => {
+                        this.classList.push(groups)
+                    })
+                }
                 if(res.members.length) {
+                    this.stuTotal += res.members.length
                     let arr = this._.cloneDeep(res.members)
                     // type表示角色类型,1:醍摩豆登陆,2:学生登陆
-                    this.stuList = arr.map((item) => {
+                    let arrlist = arr.map((item) => {
                         if(item.id === this.$store.state.userInfo.sub) {
                             item.name = `${item.name}(${this.$t("studentWeb.courseContent.me")})`
                         }
@@ -718,6 +743,7 @@ export default {
                         }
                         return item
                     })
+                    this.stuList.push(arrlist)
                     /* this.stuList = arr.filter((item) => {
                         return item.type === 2
                     }) */
@@ -847,6 +873,8 @@ export default {
                     this.getClassTime()
                     if(schclassIds.length) {
                         this.getClassName(schclassIds, true)
+                    } else {
+                        this.updataList(this.fixList)
                     }
                     if(classIds.length) {
                         this.getClassName(classIds)
@@ -854,6 +882,11 @@ export default {
                 }
             }).finally(()=>{
                 this.isLoad = false
+                if(this.fixList.length) {
+                    this.clickCell(this.fixList[0], 0, "list")
+                } else if(this.personList.length){
+                    this.clickCell(this.personList[0], 0, "list")
+                }
             })
         },
         // 课程的相关信息(attribute: "class/person")
@@ -996,11 +1029,11 @@ export default {
                 }).catch(e => {
                     console.log(e);
                 }).finally(() => {
-                    if(this.fixList.length) {
+                    /* if(this.fixList.length) {
                         this.clickCell(this.fixList[0], 0, "list")
                     } else if(this.personList.length){
                         this.clickCell(this.personList[0], 0, "list")
-                    }
+                    } */
                 })
             // })
         },
@@ -1012,6 +1045,7 @@ export default {
         clickCell(row, index, type) {
             this.name = "tab5"
             this.continuationToken = null
+            this.courseIndex = this.stuTotal = this.recordNum = 0
             let nowClassInfor = undefined
             if(type) {
                 nowClassInfor = this._.cloneDeep(row)
@@ -1019,11 +1053,14 @@ export default {
                 nowClassInfor = this._.cloneDeep(row.fixList[index])
             }
             this.unique = nowClassInfor.unique
+            this.getSas(nowClassInfor)
             this.sentSelectedEventTitle(nowClassInfor)
         },
         // 跳转到当前课程
         sentSelectedEventTitle(item) {
             this.tmdList = []
+            this.stuList = []
+            this.classList = []
             this.isLoad = true
             this.courseNow = this._.cloneDeep(item)
             this.needParam = {
@@ -1034,16 +1071,22 @@ export default {
                 userid: this.courseNow.teaId,
             }
             // 获取学生名单
-            if(this.courseNow.classId != "" && this.courseNow.classId) {
-                this.findStuInfor(this.courseNow, true)
-                this.needParam.classes = [this.courseNow.classId]
-            } else if(this.courseNow.stuList != "") {
+            if(this.courseNow.classId.length) {
+                this.courseNow.classId.forEach(cour => {
+                    this.findStuInfor(cour, true)
+                })
+                this.needParam.classes = this.courseNow.classId
+            } else if(this.courseNow.stuList.length) {
                 // this.findPersonInfo(this.courseNow)
-                this.findStuInfor(this.courseNow)
-                this.needParam.classes = [this.courseNow.stuList]
+                // this.findStuInfor(this.courseNow)
+                this.courseNow.stuList.forEach(stu => {
+                    this.findStuInfor(stu)
+                })
+                this.needParam.classes = this.courseNow.stuList
             }
             this.recordList = []
-            this.getRecordList()
+            // this.getRecordList()
+            this.getRecordNum()
             // 螢幕寬度<767px時,直接關掉sidebar
             if (window.innerWidth <= 991) {
                 this.$store.commit("ToggleSidebar", false);
@@ -1076,6 +1119,28 @@ export default {
                 }, 2000);
             });
         },
+        getRecordNum() {
+            let param = {
+                tmdid: this.courseNow.teaId,
+                scope: this.courseNow.scope, //school:传school,private:传tmdid
+                school: "",
+                category: [],
+                subjectId: [],
+                courseId: this.courseNow.id,
+                grade: [],
+                doubleGreen: false,
+                quality: false,
+                DESC: "startTime",
+                pageCount: 10, //返回六条数据(分页)
+                today: false,
+                continuationToken: this.continuationToken, //返回的有值的话,下次查询就要用这个值
+            }
+            param.scope === "school" ? param.school = this.userInfo.azp : param.tmdid = this.courseNow.creatorId
+            this.$api.studentWeb.getRecordNum(param).then(res => {
+                this.recordNum = res.count
+                this.getRecordList()
+            })
+        },
         getRecordList() {
             // this.recordList = []
             let param = {
@@ -1103,12 +1168,18 @@ export default {
                         let mins = min >= 60 ? min % 60 : min
                         let hour = parseInt(min / 60)
                         item.time = `${hour < 10 ? ('0' + hour) : hour}:${mins < 10 ? ('0' + mins) : mins}:${sec < 10 ? ('0' + sec) : sec}`
+                        item.eNote = `${this.sasInfo.url}/${this.sasInfo.name}/records/${item.id}/Note.pdf?${this.sasInfo.sas}`
+                        item.CoverImage = `${this.sasInfo.url}/${this.sasInfo.name}/records/${item.id}/Record/CoverImage.jpg?${this.sasInfo.sas}`
                     })
                     this.recordList.push.apply(this.recordList, res.lessonRecords)
                     this.continuationToken = res.continuationToken
                 }
             })
         },
+        async getSas(info) {
+            let code = info.scope === "school" ? this.userInfo.azp : info.creatorId
+            this.sasInfo = await this.$tools.getBlobSas(code)
+        },
         toClassRecord(item, index) {
             this.nowIndex = index
             this.$router.push({
@@ -1152,12 +1223,16 @@ export default {
                 })
             }
         },
+        uploadNote(info) {
+            this.$tools.doDownloadByUrl(info.eNote, info.name)
+        },
     },
 
     created() {
         this.$emit("onNavNo", this.MyNo);
         this.$emit("onNavName", this.MyName);
         this.$store.commit("ToggleSidebar", true);
+        // this.getSas()
         this.findSchoolInfo()
         this.onlyStu = this.userInfo.scope != 'tmduser'
         this.getClassList()

+ 2 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js

@@ -82,7 +82,8 @@ export default {
         copyContent: 'Are you sure to copy the assessment?',
         copyContent1: 'Smarter Classroom Assessment cannot be copied.',
         paperExam:'紙本測驗',
-        loadAll:'已加載所有數據'
+        loadAll:'已加載所有數據',
+        crossSchool:'跨校評測,在當前學校無法查看發布對象'
     },
 
     //CreateEv

+ 6 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/studentWeb.js

@@ -581,7 +581,12 @@ export default {
             allClass: 'All Class',
             participantClass: 'Whole Class',
             participantAverage: 'Whole School',
-            recognizePerformance: 'Cognitive Level Radar Chart'
+            recognizePerformance: 'Cognitive Level Radar Chart',
+            legendSimple: {
+                legend1: "比率:全班的試題答對率",
+                legend2: "答對:",
+                legend3: "答錯:",
+            },
         },
         studentScore: {
             examName: 'Exam Name',

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/learnActivity.js

@@ -83,6 +83,7 @@ export default {
         copyContent1: '课中评测不能进行复制操作。',
         paperExam:'纸本测验',
         loadAll:'已加载所有数据',
+        crossSchool:'跨校评测,在当前学校无法查看发布对象'
     },
 
     //CreateEv

+ 6 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/studentWeb.js

@@ -581,7 +581,12 @@ export default {
             allClass: '所有班级',
             participantClass: '全班',
             participantAverage: '全校',
-            recognizePerformance: '认知层次雷达图'
+            recognizePerformance: '认知层次雷达图',
+            legendSimple: {
+                legend1: "比率:全班的试题答对率",
+                legend2: "答对:",
+                legend3: "答错:",
+            },
         },
         studentScore: {
             examName: '考试名称',

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js

@@ -83,6 +83,7 @@ export default {
         copyContent1: '課中評量不能進行複製操作。',
         paperExam:'紙本測驗',
         loadAll:'已加載所有數據',
+        crossSchool:'跨校評測,在當前學校無法查看發布對象'
     },
 
     //建立評量學校/個人

+ 6 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/studentWeb.js

@@ -581,7 +581,12 @@ export default {
             allClass: '所有班級',
             participantClass: '全班',
             participantAverage: '全校',
-            recognizePerformance: '認知層次雷達圖'
+            recognizePerformance: '認知層次雷達圖',
+            legendSimple: {
+                legend1: "比率:全班的試題答對率",
+                legend2: "答對:",
+                legend3: "答錯:",
+            },
         },
         studentScore: {
             examName: '考試名稱',

+ 40 - 41
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -7,15 +7,15 @@
                 <Icon style="display:block" custom="iconfont icon-home" :color="isHomeLight ? '#1CC0F3':'#d0d0d0'" @click="toHome" :title="$t('system.goHome')" />
                 <Icon type="md-open" @click="changePlatform" :title="$t('system.changePlat')" v-if="hasArea" />
                 <!-- <Icon type="md-help-circle" @click="goHelpDoc" :title="$t('system.help')" v-if="!inJinNiu" /> -->
-				<Icon type="md-help-circle" @click="goHelpDoc" :title="$t('system.help')" v-if="!inGlobalSite && !inJinNiu"/>
-				<Icon type="md-text" @mouseover.native="isShowQrCode = true" @mouseleave.native="isShowQrCode = false" v-if="!inGlobalSite && !inJinNiu"/>
+                <Icon type="md-help-circle" @click="goHelpDoc" :title="$t('system.help')" v-if="!inGlobalSite && !inJinNiu" />
+                <Icon type="md-text" @mouseover.native="isShowQrCode = true" @mouseleave.native="isShowQrCode = false" v-if="!inGlobalSite && !inJinNiu" />
                 <BaseNotification :msgs="msgs"></BaseNotification>
                 <span class="header-split"></span>
                 <BaseUserPoptip @logout="basicMenu('quit')"></BaseUserPoptip>
-				<div class="overlay-qrcode" v-show="isShowQrCode">
-					<img src="../assets/image/qrcode.png" width="150px">
-					<p style="margin-top: 10px;">{{ $t('system.wechatTip') }}</p>
-				</div>
+                <div class="overlay-qrcode" v-show="isShowQrCode">
+                    <img src="../assets/image/qrcode.png" width="150px">
+                    <p style="margin-top: 10px;">{{ $t('system.wechatTip') }}</p>
+                </div>
             </div>
             <div id="content" slot="content">
                 <router-view v-if="!$route.meta.isKeep && isRouterAlive" :key="this.$route.name"></router-view>
@@ -75,7 +75,7 @@ export default {
     },
     data() {
         return {
-			isShowQrCode:false,
+            isShowQrCode: false,
             updStatus: false,
             isRouterAlive: true,
             msgs: [],
@@ -100,9 +100,8 @@ export default {
         let webEndTime = localStorage.getItem('webEndTime')
         let time_now = new Date().getTime()
         if (webEndTime && time_now > webEndTime) {
-            console.log('长时间未操作,清空storage,重新登录')
             this.loginOut()
-            localStorage.setItem('loginOut','Home检查长时间未操作')
+            sessionStorage.setItem('loginOut', 'Home检查长时间未操作')
         }
         this.$store.dispatch('user/checkSchoolCode'); // 設定登入成功的學校簡碼
         this.$store.dispatch('user/checkUserProfile'); // 檢查使用者個人詳細資訊
@@ -341,9 +340,9 @@ export default {
         inJinNiu() {
             return window.location.host === 'jinniu.teammodel.cn'
         },
-		inGlobalSite(){
-			return localStorage.getItem('location') === 'Global'
-		}
+        inGlobalSite() {
+            return localStorage.getItem('location') === 'Global'
+        }
     },
     watch: {
         $route: {
@@ -422,37 +421,37 @@ export default {
     float: right;
     height: 25px;
     padding-right: 20px;
-	position: relative;
+    position: relative;
+}
+
+.header-right-box .overlay-qrcode {
+    position: absolute;
+    right: 115px;
+    bottom: -215px;
+    background-color: #fff;
+    padding: 10px;
+    border-radius: 8px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    font-size: 12px;
+    border: 1px solid #dfdfdf;
 }
 
-.header-right-box .overlay-qrcode{
-		position: absolute;
-		right: 115px;
-		bottom: -215px;
-		background-color: #fff;
-		padding: 10px;
-		border-radius: 8px;
-		display: flex;
-		flex-direction: column;
-		align-items: center;
-		justify-content: center;
-		font-size: 12px;
-		border: 1px solid #dfdfdf;
-	}
-	
-	.header-right-box .overlay-qrcode::before{
-		width: 0;
-		height: 0;
-		border-style: solid;
-		border-width: 12px 12px 12px 0;
-		border-color: transparent #F7F7F7 transparent transparent;
-		content: '\A';
-		position: absolute;
-		left: 78px;
-		top: -18px;
-		border-right-color: #d9d9d9;
-		transform: rotate(90deg);
-	}
+.header-right-box .overlay-qrcode::before {
+    width: 0;
+    height: 0;
+    border-style: solid;
+    border-width: 12px 12px 12px 0;
+    border-color: transparent #f7f7f7 transparent transparent;
+    content: "\A";
+    position: absolute;
+    left: 78px;
+    top: -18px;
+    border-right-color: #d9d9d9;
+    transform: rotate(90deg);
+}
 
 .header-right-box .ivu-icon {
     font-size: 20px;

+ 15 - 1
TEAMModelOS/ClientApp/src/view/assessment/Assessment.vue

@@ -283,6 +283,14 @@
 						{{ row.type === 'school' ? '校评' : '互评' }}
 					</Tag>
 				</template>
+				<template slot-scope="{ row }" slot="score">
+				  <p style="font-weight: bold;">
+				    <span v-show="row.score === 2" style="color: #007700;">{{ $t('jyzx.application.fine') }}</span>
+				    <span v-show="row.score === 1" style="color: orangered;">{{ $t('jyzx.application.qualified') }}</span>
+				    <span v-show="row.score === 0" style="color: red;">{{ $t('jyzx.application.unqualified') }}</span>
+				    <span v-show="row.score === -1" style="color: red;">-</span>
+				  </p>
+				</template>
 			</Table>
 		</Modal>
 		<!-- 展示作业提交PDF选择弹窗 -->
@@ -598,10 +606,14 @@
 						title: `评价类型`,
 						slot: 'type'
 					},
+					{
+						title: `评价结果`,
+						slot: 'score',
+					},
 					{
 						title: this.$t('jyzx.application.evaContent'),
 						key: 'content',
-						width: 600
+						width: 500
 					},
 					{
 						title: `评论时间`,
@@ -857,6 +869,7 @@
 								result.push({
 									name: j.tmdname,
 									type: i.roleType,
+									score: i.score,
 									content: j.comment,
 									atName:userInfo.name,
 									time: this.$tools.formatTime(j.time,
@@ -867,6 +880,7 @@
 							result.push({
 								name: i.tmdname,
 								type: i.roleType,
+								score: i.score,
 								content: `无评价内容`,
 								atName:userInfo.name,
 								time: this.$tools.formatTime(i.time, 'yyyy-MM-dd hh:mm')

+ 0 - 2
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.less

@@ -179,8 +179,6 @@
     margin-bottom: 10px;
     position: relative;
     min-height: 300px;
-    height:750px;
-    
 }
 
 .class-file-wrap {

+ 58 - 55
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -79,45 +79,48 @@
                             <Icon :class="typeIndex == 'file' ? 'type-icon-active type-icon':'type-icon'" type="md-document" @click="filterType('file')" :title="$t('cusMgt.rcd.file')" />
                             <Icon :class="typeIndex == 'link' ? 'type-icon-active type-icon':'type-icon'" type="ios-link" @click="filterType('link')" :title="$t('cusMgt.rcd.link')" />
                         </div> -->
-                        <vuescroll ref="datawrap">
-                            <template v-for="(item,index) in pageList">
-                                <div v-if="item.pageData" class="page-item" :key="index" :id="'page'+(item.page)">
-                                    <div class="page-info-wrap">
-                                        <span class="page-tag" @click="toVideo(index+1,$event)" :ref="'page'+(index+1)">
-                                            {{`${$t('cusMgt.rcd.cw')}${item.page}${$t('cusMgt.rcd.page')}`}}
-                                        </span>
-                                        <!-- 课件缩略图 -->
-                                        <!-- <img class="page-mini-img" @click="openViewer(item.img)" :src="item.img" /> -->
-                                        <!-- <Timeline style="margin-top:10px;margin-left:-5px">
+                        <!-- <vuescroll ref="datawrap"> -->
+                        <template v-for="(item,index) in pageList">
+                            <div v-if="item.pageData && item.pageData.length" class="page-item" :key="index" :id="'page'+(item.page)">
+                                <div class="page-info-wrap">
+                                    <span class="page-tag" @click="toVideo(index+1,$event)" :ref="'page'+(index+1)">
+                                        {{`${$t('cusMgt.rcd.cw')}${item.page}${$t('cusMgt.rcd.page')}`}}
+                                    </span>
+                                    <!-- 课件缩略图 -->
+                                    <!-- <img class="page-mini-img" @click="openViewer(item.img)" :src="item.img" /> -->
+                                    <!-- <Timeline style="margin-top:10px;margin-left:-5px">
                                             <TimelineItem v-for="(rtItem, rtIndex) in item.pageData" :key="rtIndex +''+index">
                                                 <Icon type="md-arrow-dropright" slot="dot" />
                                                 <p class="event-tag" @click="toEvent(rtItem)">{{rtItem.eventName}}</p>
                                             </TimelineItem>
                                         </Timeline> -->
+                                </div>
+                                <div class="record-data-wrap">
+                                    <!-- <EmptyData v-if="!item.pageData.length" :textContent="$t('cusMgt.rcd.pageNoRcd')"></EmptyData> -->
+                                    <!-- <p v-if="!item.pageData.length" style="color:#c0c0c0;padding-top:4px">
+                                        {{$t('cusMgt.rcd.pageNoRcd')}}
+                                    </p> -->
+                                    <!-- <template v-else> -->
+                                    <!-- 互动数据 -->
+                                    <div v-for="event in item.pageData" :key="event.Time">
+                                        <!-- 即问即答 -->
+                                        <PopQues class="event-item" v-if="event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt'" :evtType="event.Event" :irsData="event.data"></PopQues>
+                                        <!-- 抢权 -->
+                                        <Buzr class="event-item student-event" v-else-if="event.Event === 'BuzrAns'" :buzrData="event.data" :students="baseData.student"></Buzr>
+                                        <!-- 推送 -->
+                                        <Push class="event-item" v-else-if="event.Event === 'FastPgPush'" :pushData="event.data"></Push>
+                                        <!-- 作品收集 -->
+                                        <Receive :recordInfo="recordInfo" class="student-event event-item" v-else-if="event.Event === 'WrkSpaceEnd'" :rcvData="event.data" :students="baseData.student"></Receive>
+                                        <!-- 随机挑人 -->
+                                        <Pick class="event-item student-event" :pickData="event.data" v-else-if="event.Event === 'PickupResult'" :students="baseData.student"></Pick>
+                                        <!-- 课中评测 -->
+                                        <Exam class="event-item" :examInfo="event.data" :recordInfo="recordInfo" v-else-if="event.Event === 'SPQStrt'"></Exam>
                                     </div>
-                                    <div class="record-data-wrap">
-                                        <EmptyData v-if="!item.pageData.length" :textContent="$t('cusMgt.rcd.pageNoRcd')"></EmptyData>
-                                        <!-- <template v-else> -->
-                                        <!-- 互动数据 -->
-                                        <div v-for="event in item.pageData" :key="event.Time">
-                                            <!-- 即问即答 -->
-                                            <PopQues class="event-item" v-if="event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt'" :evtType="event.Event" :irsData="event.data"></PopQues>
-                                            <!-- 抢权 -->
-                                            <Buzr class="event-item student-event" v-else-if="event.Event === 'BuzrAns'" :buzrData="event.data" :students="baseData.student"></Buzr>
-                                            <!-- 推送 -->
-                                            <Push class="event-item" v-else-if="event.Event === 'FastPgPush'" :pushData="event.data"></Push>
-                                            <!-- 作品收集 -->
-                                            <Receive :recordInfo="recordInfo" class="student-event event-item" v-else-if="event.Event === 'WrkSpaceEnd'" :rcvData="event.data" :students="baseData.student"></Receive>
-                                            <!-- 随机挑人 -->
-                                            <Pick class="event-item student-event" :pickData="event.data" v-else-if="event.Event === 'PickupResult'" :students="baseData.student"></Pick>
-                                            <!-- 课中评测 -->
-                                            <Exam class="event-item" :examInfo="event.data" :recordInfo="recordInfo" v-else-if="event.Event === 'SPQStrt'"></Exam>
-                                        </div>
-                                        <!-- </template> -->
-                                    </div>
+                                    <!-- </template> -->
                                 </div>
-                            </template>
-                        </vuescroll>
+                            </div>
+                        </template>
+                        <!-- </vuescroll> -->
                     </div>
                 </div>
             </div>
@@ -224,12 +227,12 @@ export default {
                 },
                 300
             )
-            this.$refs['datawrap'].scrollTo(
-                {
-                    y: '0'
-                },
-                300
-            )
+            // this.$refs['datawrap'].scrollTo(
+            //     {
+            //         y: '0'
+            //     },
+            //     300
+            // )
         },
         //跳转到对应事件
         toEvent(event) {
@@ -403,7 +406,7 @@ export default {
         },
         //点击视频切片
         getCurPage(page) {
-            this.$refs["datawrap"].scrollIntoView('#page' + page, 500)
+            // this.$refs["datawrap"].scrollIntoView('#page' + page, 500)
             this.$refs.videoPlayer.player.play()
             this.curPage = page
         },
@@ -421,28 +424,28 @@ export default {
                 this.$refs.videoPlayer.player.currentTime(pageInfo.time)
                 this.$refs.videoPlayer.player.play()
             } else {
-                this.$refs["datawrap"].scrollIntoView('#page' + page, 500)
+                // this.$refs["datawrap"].scrollIntoView('#page' + page, 500)
             }
         },
         //点击互动记录页面tag
         toVideo(page, e) {
             //页面滚动
-            let dataLoacation = this.$refs["datawrap"].getPosition()
-            let pageLocaltion = this.$refs["pagewrap"].getPosition()
-            let y = e.pageY - 665 + pageLocaltion.scrollTop + dataLoacation.scrollTop
+            // let dataLoacation = this.$refs["datawrap"].getPosition()
+            // let pageLocaltion = this.$refs["pagewrap"].getPosition()
+            // let y = e.pageY - 665 + pageLocaltion.scrollTop + dataLoacation.scrollTop
             this.$nextTick(() => {
-                this.$refs["pagewrap"].scrollTo(
-                    {
-                        x: 0,
-                        y: 0
-                    }
-                )
-                this.$refs["datawrap"].scrollTo(
-                    {
-                        x: 0,
-                        y: y
-                    }
-                )
+                // this.$refs["pagewrap"].scrollTo(
+                //     {
+                //         x: 0,
+                //         y: 0
+                //     }
+                // )
+                // this.$refs["datawrap"].scrollTo(
+                //     {
+                //         x: 0,
+                //         y: y
+                //     }
+                // )
             })
             // 教材页面切换
             this.curPage = page

+ 7 - 2
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/Receive.vue

@@ -2,7 +2,8 @@
     <!-- 作品收集 -->
     <div class="receive-wrap">
         <p class="clt-type">
-            {{cltTypeMap[collateType].text}}收集:
+            <!-- {{cltTypeMap[collateType].text}}收集:{{collateType}} -->
+            收集:{{collateType}}
         </p>
         <div v-for="(item) in receiveData" :key="item.seatID+item.groupID" class="receive-item">
             <div v-if="collateType == 0">
@@ -175,7 +176,11 @@ export default {
             deep: true,
             immediate: true,
             handler(n, o) {
-                this.collateType = n.collateType
+                console.log('作品收集:', n)
+                if (n && n.collateType) {
+                    this.collateType = n.collateType
+                }
+
                 // if (n.clientWorks) {
                 //     this.receiveData = this._.cloneDeep(n.clientWorks)
                 //     let blobInfo = this.recordInfo.scope == 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile

+ 1 - 1
TEAMModelOS/ClientApp/src/view/dashboard/Research.vue

@@ -78,7 +78,7 @@
 	import RightTop from '@/components/research-dashboard/RightTop'
 	import bottomRight from '@/components/research-dashboard/bottomRight'
 	export default {
-		mixins: [drawMixin],
+		// mixins: [drawMixin],
 		data() {
 			return {
 				timing: null,

+ 3 - 3
TEAMModelOS/ClientApp/src/view/jyzx/classMemoir.vue

@@ -7,14 +7,14 @@
                         <div class="uploaddiv"><AbilityUpload ref="refFile" :auth="curSas" :acceptTypes="['mp4']" :scope="'school'" mode='video' :prefix="uploadId" @uploadFinish="uploadFinish" singleUpload></AbilityUpload></div>
                         <div class="hint" v-show="calssListinfo.length !==0">{{tipText}}</div>
                         <Button type="primary" size="large" :long="true" @click="confirm" v-if="!calssListinfo.length" :loading="btnstate">{{ $t('jyzx.classRecord.loadOK') }}</Button>
-                        <Button type="info" size="large" :long="true" disabled v-else-if="calssListinfo[0].score ==1 ||calssListinfo[0].score ==2">{{ $t('jyzx.classRecord.loadOK') }}</Button>
-                        <Button type="info" size="large" :long="true" @click="confirm" v-else="calssListinfo[0].score !==1 ||calssListinfo[0].score !==2" :loading="btnstate">重新上传</Button>
+                        <Button type="info" size="large" :long="true" disabled v-else-if="calssListinfo[calssListinfo.length-1].score ==1 ||calssListinfo[calssListinfo.length-1].score ==2">{{ $t('jyzx.classRecord.loadOK') }}</Button>
+                        <Button type="info" size="large" :long="true" @click="confirm" v-else="calssListinfo[calssListinfo.length-1].score !==1 ||calssListinfo[calssListinfo.length-1].score !==2" :loading="btnstate">重新上传</Button>
                     </div>
                     <div v-if="calssListinfo.length" style="height: calc(100vh - 255px); overflow: auto; margin-top: 20px">
                         <Table :columns="classCol" :data="calssListinfo" height="680">
                             <template slot-scope="{ row, index }" slot="action">
                                 <Button size="small" @click="checkevaluate(row,true)" style="margin-right:2%">{{ $t('jyzx.common.seeEvaluate') }}</Button>
-                                <Button size="small" @click="delClass(row)" v-if="calssListinfo[0].score !==1 && calssListinfo[0].score !==2" class="delete-btns">{{ $t('jyzx.common.delete') }}</Button>
+                                <Button size="small" @click="delClass(row)" v-if="calssListinfo[calssListinfo.length-1].score !==1 && calssListinfo[calssListinfo.length-1].score !==2" class="delete-btns">{{ $t('jyzx.common.delete') }}</Button>
                             </template>
                         </Table>
                     </div>

+ 26 - 21
TEAMModelOS/ClientApp/src/view/learnactivity/ExamMgt.vue

@@ -63,19 +63,6 @@
                                     {{ item.scoreText }}
                                 </span>
                                 <Icon class="exam-target" size="20" type="ios-people" @click="getExamTarget(item)" />
-                                <!-- <Tooltip @on-popper-show="getExamTarget(item)">
-                                        <Icon class="exam-target" size="20" type="ios-people" />
-                                        <div slot="content" style="padding-left:15px;min-width:180px">
-                                            <p style="margin-left:-15px">
-                                                {{$t('learnActivity.createEv.evTarget')}}:
-                                            </p>
-                                            <ul>
-                                                <li v-for="item in examTargets" :key="item.id">
-                                                    {{item.name}}
-                                                </li>
-                                            </ul>
-                                        </div>
-                                    </Tooltip> -->
                             </div>
                             <!-- 立即结束 和评测状态 按钮-->
                             <span v-if="item.progress == 'going'" class="handle-end-tag ev-tag-common" @click="handleEnd(index)">
@@ -126,8 +113,10 @@
                         {{$t('learnActivity.mgtScEv.markSetting')}}
                     </span>
                 </div>
+                <!-- 跨校个人评测提示UI -->
+                <CrossSchool v-if="examDetaiInfo && !examDetaiInfo.curSchool" :examInfo="examDetaiInfo"></CrossSchool>
                 <!-- 评测数据 -->
-                <DataView v-if="curBarIndex == 0" :examInfo="examDetaiInfo" :correctData="correctData" :simpleData="simpleData" :dataErr="dataErr" class="evaluation-base-info"></DataView>
+                <DataView v-else-if="curBarIndex == 0" :examInfo="examDetaiInfo" :correctData="correctData" :simpleData="simpleData" :dataErr="dataErr" class="evaluation-base-info"></DataView>
                 <!-- 作答详情 -->
                 <AnswerTable v-else-if="curBarIndex == 3" :examInfo="examDetaiInfo" :correctData="correctData" class="evaluation-base-info"></AnswerTable>
                 <!-- 评测试卷 -->
@@ -168,6 +157,7 @@
     </div>
 </template>
 <script>
+import CrossSchool from "./tabs/CrossSchool.vue"
 import DataView from "./tabs/DataView.vue"
 import AnswerTable from "./tabs/AnswerTable.vue"
 import ExamPaper from "./tabs/ExamPaper.vue"
@@ -175,7 +165,7 @@ import ExamTask from "./tabs/ExamTask.vue"
 import MarkSetting from "./markpaper/MarkSetting.vue"
 export default {
     components: {
-        DataView, AnswerTable, ExamPaper, ExamTask, MarkSetting
+        DataView, AnswerTable, ExamPaper, ExamTask, MarkSetting, CrossSchool
     },
     data() {
         return {
@@ -229,10 +219,10 @@ export default {
                 }
             }
         },
-        evAuthStatus(){
-            if(this.scope == 'school'){
+        evAuthStatus() {
+            if (this.scope == 'school') {
                 return this.$access.can('admin.*|schoolAc-upd')
-            }else{
+            } else {
                 return true
             }
         }
@@ -266,7 +256,16 @@ export default {
             this.filterEv()
         },
         getExamTarget(data) {
+            // 跨校评测
+            if (data.scope == 'school' && !data.curSchool) {
+                this.$Modal.info({
+                    title: this.$t('learnActivity.createEv.evTarget'),
+                    content:this.$t('learnActivity.mgtScEv.crossSchool')
+                })
+                return
+            }
             let ids = data.classes && data.classes.length ? data.classes : data.stuLists
+            if (!ids) return
             this.$api.common.getGroupListByIds({
                 ids,
                 schoolId: this.$store.state.userInfo.schoolCode
@@ -445,12 +444,12 @@ export default {
                     count: this.pageCount
                 }
                 //判断是否加载完所有数据
-                if(this.ctnToken == 'end'){
+                if (this.ctnToken == 'end') {
                     this.$Message.success(this.$t('learnActivity.mgtScEv.loadAll'))
                     r()
                     return
                 }
-                if(this.ctnToken) requestData.token = this.ctnToken
+                if (this.ctnToken) requestData.token = this.ctnToken
                 //校本评测根据学段查询
                 if (this.scope == 'school') requestData.period = this.filterPeriod
                 //添加其他查询条件
@@ -470,6 +469,7 @@ export default {
                                 item.progColor = statusInfo.progColor
                                 item.scoreText = statusInfo.scoreText
                                 item.scoreColor = statusInfo.scoreColor
+                                item.curSchool = !(item.scope === 'school' && item.school != this.$store.state.userInfo.schoolCode)
                             })
                             this.evaListShow.push(...res.examInfo)
                             if (res.examInfo.length) {
@@ -524,6 +524,11 @@ export default {
             this.curSubIndex = 0
             this.curEvaIndex = index
             sessionStorage.setItem('examScope', this.evaListShow[index].scope)
+            //跨校个人评测
+            if (!this.evaListShow[this.curEvaIndex].curSchool) {
+                this.examDetaiInfo = this.evaListShow[this.curEvaIndex]
+                return
+            }
             if (this.evaListShow[this.curEvaIndex].progress == 'going' && this.curBarIndex === 0) {
                 this.curBarIndex = 3
             }
@@ -588,7 +593,7 @@ export default {
                             resData.progColor = statusInfo.progColor
                             resData.scoreText = statusInfo.scoreText
                             resData.scoreColor = statusInfo.scoreColor
-
+                            resData.curSchool = !(resData.scope === 'school' && resData.school != this.$store.state.userInfo.schoolCode)
                             //设置各科题号信息
                             this.setPaperQuInfo(resData.papers)
                         }

+ 18 - 11
TEAMModelOS/ClientApp/src/view/learnactivity/echarts/KngPoint.vue

@@ -1,13 +1,13 @@
 <template>
     <div class="recognize-perform-chart">
-        <div v-if="!knowledge.kn || !knowledge.kn.length" class="no-kn-point">
+        <div v-show="!hasKn" class="no-kn-point">
             <p class="chart-title">{{$t('studentWeb.exam.chart.keyPointPerformance')}}</p>
             <img src="@/assets/image/none.png" alt="" class="tips-img">
             <p class="chart-text">
                 {{$t('learnActivity.simple.noKn')}}
             </p>
         </div>
-        <div :id="'knowledge'+id" style="width: 306px; height: 300px;margin:auto" v-else></div>
+        <div v-show="hasKn" :id="'knowledge'+id" style="width: 306px; height: 300px;margin:auto"></div>
     </div>
 </template>
 
@@ -33,6 +33,11 @@ export default {
             myChart: undefined
         }
     },
+    computed: {
+        hasKn() {
+            return !!(this.knowledge.kn && this.knowledge.kn.length)
+        }
+    },
     created() {
         this.id = this.$jsFn.getBtwRandom(0, 100000000)
     },
@@ -96,20 +101,22 @@ export default {
         // }
     },
     watch: {
-        deep: true,
         knowledge: {
+            deep: true,
+            immediate: true,
             handler(n, o) {
-                if (n.kn && n.kn.length) {
-                    this.$nextTick(() => {
+                this.$nextTick(() => {
+                    console.log('知识点', n)
+                    if (n.kn && n.kn.length) {
                         this.getFiled()
                         this.setMap()
-                    })
-                } else {
-                    if (this.myChart) {
-                        this.myChart.dispose()
-                        this.myChart = undefined
+                    } else {
+                        if (this.myChart) {
+                            this.myChart.dispose()
+                            this.myChart = undefined
+                        }
                     }
-                }
+                })
             }
         }
     }

+ 1 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/AnswerTable.less

@@ -1,5 +1,5 @@
 .data-count-wrap{
-    padding: 15px 0px;
+    padding: 20px 0px;
     display: flex;
     background: white;
     justify-content: space-between;

+ 1 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/AnswerTable.vue

@@ -464,6 +464,7 @@ export default {
                 this.chooseClass = ''
                 //这里统一获取名单数据(教学班、行政班、个人名单)
                 let ids = n.stuLists?.length ? n.stuLists : n.classes
+                if (!ids) return
                 let params = {
                     'schoolId': this.$store.state.userInfo.schoolCode,
                     'ids': ids

+ 68 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/CrossSchool.vue

@@ -0,0 +1,68 @@
+<template>
+    <div class="cross-school-container">
+        <div class="toggle-school-box">
+            <img src="@/assets/image/unauth.svg" alt="" class="unauth-img">
+            <p class="toggle-school-text">
+                {{$t('learnActivity.mgtScEv.tst1')}}
+                <strong style="color:#2d8cf0">{{getSchoolName(examInfo.school)}}</strong>
+                {{$t('learnActivity.mgtScEv.tst2')}}
+            </p>
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    props:{
+        examInfo:{
+            type:Object,
+            default:()=>{
+                return {}
+            }
+        }
+    },
+    data() {
+        return {
+
+        }
+    },
+    methods: {
+        getSchoolName(school) {
+            let schools = this.$store.state?.user?.userProfile?.schools
+            if (schools) {
+                let s = schools.find(item => item.schoolId === school)
+                return s ? s.name : school
+            }
+            return school
+        },
+    }
+}
+</script>
+<style scoped lang="less">
+.toggle-school-box {
+    width: fit-content;
+    margin: auto;
+    text-align: center;
+    margin-top: 150px;
+}
+.unauth-img {
+    width: 100px;
+    margin-bottom: 32px;
+}
+.toggle-school-text {
+    // margin-top: 10px;
+    color: #515a6e;
+    font-size: 16px;
+}
+.toggle-school-btn {
+    margin: auto;
+    width: fit-content;
+    background: #2b85e4;
+    color: white;
+    padding: 8px 40px;
+    border-radius: 30px;
+    font-size: 16px;
+    margin-top: 16px;
+    cursor: pointer;
+    user-select: none;
+}
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/DataView.less

@@ -3,7 +3,7 @@
     background: #f6f6f6;
 }
 .data-count-wrap{
-    padding: 15px 0px;
+    padding: 20px 0px;
     display: flex;
     background: white;
     justify-content: space-between;

+ 69 - 8
TEAMModelOS/ClientApp/src/view/newcourse/ClassTable.vue

@@ -130,7 +130,17 @@
                 </FormItem>
                 <FormItem :label="$t('cusMgt.teaLabel')" prop="setTea">
                     <Select v-model="schd.setTea" filterable style="width:90%;" :not-found-text="schd.setCus ? $t('cusMgt.noAddTea') : $t('cusMgt.sltCusTips')">
-                        <Option v-for="(item,index) in cusTeaList" :key="index" :value="item.id" @click.native="setTeaName(item)">{{item.name}}</Option>
+                        <!-- 当前课程教师 -->
+                        <Option v-for="(item) in cusTeaList" :key="item.id" :value="item.id" @click.native="setTeaName(item)">
+                            {{item.name}}
+                            ({{item.id}})
+                            <Icon type="md-star" color="#19be6b" />
+                        </Option>
+                        <!-- 学校其他老师 -->
+                        <Option v-for="(item) in otherTeacher" :key="item.id" :value="item.id" @click.native="setTeaName(item)">
+                            {{item.name}}
+                            ({{item.id}})
+                        </Option>
                     </Select>
                 </FormItem>
                 <FormItem :label="$t('cusMgt.nameListType')">
@@ -145,12 +155,28 @@
                 </FormItem>
                 <FormItem :label="$t('cusMgt.className')" prop="classId" v-if="schd.isClass == 1">
                     <Select v-model="schd.classId" filterable style="width:90%;">
-                        <Option v-for="(item,index) in teaClassList" :key="index" :value="item.id">{{item.name}}</Option>
+                        <!-- 当前老师的安排的班级 -->
+                        <Option v-for="(item) in teaClassList" :key="item.id" :value="item.id">
+                            {{item.name}}
+                            <Icon type="md-star" color="#19be6b" />
+                        </Option>
+                        <!-- 其他行政班 -->
+                        <Option v-for="(item) in otherClass" :key="item.id" :value="item.id">
+                            {{item.name}}
+                        </Option>
                     </Select>
                 </FormItem>
                 <FormItem :label="$t('cusMgt.nameList')" prop="stulist" v-else>
                     <Select v-model="schd.stulist" filterable style="width:90%;">
-                        <Option v-for="(item,index) in teaStuList" :key="index" :value="item.id">{{item.name}}</Option>
+                        <!-- 当前老师安排的行政班 -->
+                        <Option v-for="(item) in teaStuList" :key="item.id" :value="item.id">
+                            {{item.name}}
+                            <Icon type="md-star" color="#19be6b" />
+                        </Option>
+                        <!-- 其他行政班 -->
+                        <Option v-for="(item) in otherStuList" :key="item.id" :value="item.id">
+                            {{item.name}}
+                        </Option>
                     </Select>
                 </FormItem>
             </Form>
@@ -158,6 +184,7 @@
     </div>
 </template>
 <script>
+import { mapGetters } from 'vuex'
 export default {
     props: {
         //课程对象数据
@@ -182,7 +209,6 @@ export default {
             periodId: '',
             mLoading: true,
             cusList: [],
-            classList: [],
             roomList: [],
             stuList: [],
             setClass: '',
@@ -272,7 +298,8 @@ export default {
             let params = {
                 schoolId: this.$store.state.userInfo.schoolCode,
                 scope: 'school',
-                type: 'teach'
+                type: 'teach',
+                periodId: this.periodId
             }
             this.$api.common.getGroupList(params).then(
                 res => {
@@ -323,9 +350,13 @@ export default {
             this.schd.stulist = ''
         },
         copyCell(row, col) {
+            console.log(this.schd)
             let data = {
                 row,
                 col,
+                classId: this.schd.classId,
+                isClass: this.schd.classId,
+                stulist: this.schd.stulist,
                 cusId: this.schd.setCus,
                 teaId: this.schd.setTea,
                 teaName: this.schd.teaName,
@@ -377,8 +408,6 @@ export default {
                                 setTimeout(() => {
                                     this.mLoading = true
                                 })
-                            } else {
-                                // this.$Message.error('API error')
                             }
                         },
                         err => {
@@ -453,7 +482,6 @@ export default {
         this.$store.dispatch('user/getSchoolProfile').then(
             res => {
                 this.schoolBase = res.school_base
-                this.classList = res.school_classes
                 this.roomList = res.school_rooms
             },
             err => {
@@ -462,6 +490,8 @@ export default {
         )
         this.getCourseList()
         this.findStuList()
+        // 获取学校教师列表
+        this.$store.dispatch('user/getSchoolTeacher')
     },
     watch: {
         roomId() {
@@ -481,6 +511,37 @@ export default {
         }
     },
     computed: {
+        ...mapGetters({
+            teacherJoin: 'user/getTeacherJoined',
+            classList: 'user/getClasses',
+        }),
+        //未被安排到当前学校的老师
+        otherTeacher() {
+            if (this.teacherJoin && this.cusTeaList) {
+                let ids = this.cusTeaList.map(item => item.id)
+                return this.teacherJoin.filter(item => !ids.includes(item.id))
+            } else {
+                return []
+            }
+        },
+        //未被安排到当前老师的行政班
+        otherClass() {
+            if (this.classList && this.teaClassList) {
+                let ids = this.teaClassList.map(item => item.id)
+                return this.classList.filter(item => !ids.includes(item.id))
+            } else {
+                return []
+            }
+        },
+        //未被安排到当前老师的行政班
+        otherStuList() {
+            if (this.stuList && this.teaStuList) {
+                let ids = this.teaStuList.map(item => item.id)
+                return this.stuList.filter(item => !ids.includes(item.id))
+            } else {
+                return []
+            }
+        },
         //当前老师班级列表
         teaClassList() {
             let curCus = this.cusListShow.find(item => {

File diff suppressed because it is too large
+ 1190 - 1252
TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue